From e911af925f6c8c3607114f4f91e6821391b7f7e1 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 5 Oct 2023 19:30:44 +0200 Subject: [PATCH 01/36] backfilling scaffolding --- proto/pb/vm/vm.pb.go | 781 +++++++++++------- proto/pb/vm/vm_grpc.pb.go | 78 ++ proto/vm/vm.proto | 18 + .../snowman/block/mocks/state_syncable_vm.go | 30 + .../engine/snowman/block/state_syncable_vm.go | 6 + .../snowman/block/test_state_syncable_vm.go | 26 + snow/engine/snowman/transitive.go | 1 + vms/metervm/block_metrics.go | 6 +- vms/metervm/state_syncable_vm.go | 35 + vms/proposervm/state_syncable_vm.go | 12 + vms/rpcchainvm/vm_client.go | 28 + vms/rpcchainvm/vm_server.go | 10 + vms/tracedvm/block_vm.go | 2 + vms/tracedvm/state_syncable_vm.go | 25 + 14 files changed, 774 insertions(+), 284 deletions(-) diff --git a/proto/pb/vm/vm.pb.go b/proto/pb/vm/vm.pb.go index 5147dc11ccde..780c70acc419 100644 --- a/proto/pb/vm/vm.pb.go +++ b/proto/pb/vm/vm.pb.go @@ -232,7 +232,7 @@ func (x StateSummaryAcceptResponse_Mode) Number() protoreflect.EnumNumber { // Deprecated: Use StateSummaryAcceptResponse_Mode.Descriptor instead. func (StateSummaryAcceptResponse_Mode) EnumDescriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{46, 0} + return file_vm_vm_proto_rawDescGZIP(), []int{49, 0} } type InitializeRequest struct { @@ -2943,6 +2943,155 @@ func (x *GetStateSummaryResponse) GetErr() Error { return Error_ERROR_UNSPECIFIED } +type BackfillBlocksEnabledResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Err Error `protobuf:"varint,2,opt,name=err,proto3,enum=vm.Error" json:"err,omitempty"` +} + +func (x *BackfillBlocksEnabledResponse) Reset() { + *x = BackfillBlocksEnabledResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_vm_vm_proto_msgTypes[45] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BackfillBlocksEnabledResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BackfillBlocksEnabledResponse) ProtoMessage() {} + +func (x *BackfillBlocksEnabledResponse) ProtoReflect() protoreflect.Message { + mi := &file_vm_vm_proto_msgTypes[45] + 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 BackfillBlocksEnabledResponse.ProtoReflect.Descriptor instead. +func (*BackfillBlocksEnabledResponse) Descriptor() ([]byte, []int) { + return file_vm_vm_proto_rawDescGZIP(), []int{45} +} + +func (x *BackfillBlocksEnabledResponse) GetId() []byte { + if x != nil { + return x.Id + } + return nil +} + +func (x *BackfillBlocksEnabledResponse) GetErr() Error { + if x != nil { + return x.Err + } + return Error_ERROR_UNSPECIFIED +} + +type BackfillBlocksRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + BlksBytes [][]byte `protobuf:"bytes,1,rep,name=blks_bytes,json=blksBytes,proto3" json:"blks_bytes,omitempty"` +} + +func (x *BackfillBlocksRequest) Reset() { + *x = BackfillBlocksRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_vm_vm_proto_msgTypes[46] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BackfillBlocksRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BackfillBlocksRequest) ProtoMessage() {} + +func (x *BackfillBlocksRequest) ProtoReflect() protoreflect.Message { + mi := &file_vm_vm_proto_msgTypes[46] + 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 BackfillBlocksRequest.ProtoReflect.Descriptor instead. +func (*BackfillBlocksRequest) Descriptor() ([]byte, []int) { + return file_vm_vm_proto_rawDescGZIP(), []int{46} +} + +func (x *BackfillBlocksRequest) GetBlksBytes() [][]byte { + if x != nil { + return x.BlksBytes + } + return nil +} + +type BackfillBlocksResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Err Error `protobuf:"varint,1,opt,name=err,proto3,enum=vm.Error" json:"err,omitempty"` +} + +func (x *BackfillBlocksResponse) Reset() { + *x = BackfillBlocksResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_vm_vm_proto_msgTypes[47] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BackfillBlocksResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BackfillBlocksResponse) ProtoMessage() {} + +func (x *BackfillBlocksResponse) ProtoReflect() protoreflect.Message { + mi := &file_vm_vm_proto_msgTypes[47] + 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 BackfillBlocksResponse.ProtoReflect.Descriptor instead. +func (*BackfillBlocksResponse) Descriptor() ([]byte, []int) { + return file_vm_vm_proto_rawDescGZIP(), []int{47} +} + +func (x *BackfillBlocksResponse) GetErr() Error { + if x != nil { + return x.Err + } + return Error_ERROR_UNSPECIFIED +} + type StateSummaryAcceptRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2954,7 +3103,7 @@ type StateSummaryAcceptRequest struct { func (x *StateSummaryAcceptRequest) Reset() { *x = StateSummaryAcceptRequest{} if protoimpl.UnsafeEnabled { - mi := &file_vm_vm_proto_msgTypes[45] + mi := &file_vm_vm_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2967,7 +3116,7 @@ func (x *StateSummaryAcceptRequest) String() string { func (*StateSummaryAcceptRequest) ProtoMessage() {} func (x *StateSummaryAcceptRequest) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[45] + mi := &file_vm_vm_proto_msgTypes[48] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2980,7 +3129,7 @@ func (x *StateSummaryAcceptRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StateSummaryAcceptRequest.ProtoReflect.Descriptor instead. func (*StateSummaryAcceptRequest) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{45} + return file_vm_vm_proto_rawDescGZIP(), []int{48} } func (x *StateSummaryAcceptRequest) GetBytes() []byte { @@ -3002,7 +3151,7 @@ type StateSummaryAcceptResponse struct { func (x *StateSummaryAcceptResponse) Reset() { *x = StateSummaryAcceptResponse{} if protoimpl.UnsafeEnabled { - mi := &file_vm_vm_proto_msgTypes[46] + mi := &file_vm_vm_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3015,7 +3164,7 @@ func (x *StateSummaryAcceptResponse) String() string { func (*StateSummaryAcceptResponse) ProtoMessage() {} func (x *StateSummaryAcceptResponse) ProtoReflect() protoreflect.Message { - mi := &file_vm_vm_proto_msgTypes[46] + mi := &file_vm_vm_proto_msgTypes[49] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3028,7 +3177,7 @@ func (x *StateSummaryAcceptResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StateSummaryAcceptResponse.ProtoReflect.Descriptor instead. func (*StateSummaryAcceptResponse) Descriptor() ([]byte, []int) { - return file_vm_vm_proto_rawDescGZIP(), []int{46} + return file_vm_vm_proto_rawDescGZIP(), []int{49} } func (x *StateSummaryAcceptResponse) GetMode() StateSummaryAcceptResponse_Mode { @@ -3353,194 +3502,215 @@ var file_vm_vm_proto_rawDesc = []byte{ 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, 0x6d, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, - 0x31, 0x0a, 0x19, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x41, - 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, - 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, - 0x65, 0x73, 0x22, 0xc5, 0x01, 0x0a, 0x1a, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, - 0x61, 0x72, 0x79, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x37, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x23, 0x2e, 0x76, 0x6d, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, - 0x79, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, - 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x03, 0x65, 0x72, - 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, 0x6d, 0x2e, 0x45, 0x72, 0x72, - 0x6f, 0x72, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0x51, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, - 0x14, 0x0a, 0x10, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, - 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x4b, - 0x49, 0x50, 0x50, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x4d, 0x4f, 0x44, 0x45, 0x5f, - 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x4d, 0x4f, 0x44, 0x45, - 0x5f, 0x44, 0x59, 0x4e, 0x41, 0x4d, 0x49, 0x43, 0x10, 0x03, 0x2a, 0x65, 0x0a, 0x05, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x53, - 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x54, - 0x41, 0x54, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x49, 0x4e, - 0x47, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x42, 0x4f, 0x4f, - 0x54, 0x53, 0x54, 0x52, 0x41, 0x50, 0x50, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, - 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x5f, 0x4f, 0x50, 0x10, - 0x03, 0x2a, 0x61, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x12, 0x53, - 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, 0x52, - 0x4f, 0x43, 0x45, 0x53, 0x53, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x54, - 0x41, 0x54, 0x55, 0x53, 0x5f, 0x52, 0x45, 0x4a, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, - 0x13, 0x0a, 0x0f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, - 0x45, 0x44, 0x10, 0x03, 0x2a, 0x8e, 0x01, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x15, - 0x0a, 0x11, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, - 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, - 0x4c, 0x4f, 0x53, 0x45, 0x44, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x45, 0x52, 0x52, 0x4f, 0x52, - 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x12, 0x21, 0x0a, 0x1d, - 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x48, 0x45, 0x49, 0x47, 0x48, 0x54, 0x5f, 0x49, 0x4e, 0x44, - 0x45, 0x58, 0x5f, 0x49, 0x4e, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x03, 0x12, - 0x24, 0x0a, 0x20, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x53, - 0x59, 0x4e, 0x43, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x45, 0x4d, 0x45, 0x4e, - 0x54, 0x45, 0x44, 0x10, 0x04, 0x32, 0xa4, 0x12, 0x0a, 0x02, 0x56, 0x4d, 0x12, 0x3b, 0x0a, 0x0a, - 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x12, 0x15, 0x2e, 0x76, 0x6d, 0x2e, - 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x16, 0x2e, 0x76, 0x6d, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x53, 0x65, 0x74, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x13, 0x2e, 0x76, 0x6d, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x76, 0x6d, 0x2e, - 0x53, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x3a, 0x0a, 0x08, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x44, 0x0a, 0x0e, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x12, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x76, 0x6d, 0x2e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x50, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, - 0x69, 0x63, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x1a, 0x20, 0x2e, 0x76, 0x6d, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x74, - 0x61, 0x74, 0x69, 0x63, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, - 0x64, 0x12, 0x14, 0x2e, 0x76, 0x6d, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, - 0x3f, 0x0a, 0x0c, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, - 0x17, 0x2e, 0x76, 0x6d, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, - 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x12, 0x3b, 0x0a, 0x0a, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x15, - 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, - 0x0a, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x15, 0x2e, 0x76, 0x6d, - 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x76, 0x6d, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x47, 0x65, - 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x13, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x76, 0x6d, - 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x41, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, - 0x63, 0x65, 0x12, 0x18, 0x2e, 0x76, 0x6d, 0x2e, 0x53, 0x65, 0x74, 0x50, 0x72, 0x65, 0x66, 0x65, - 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x12, 0x34, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x76, 0x6d, 0x2e, 0x48, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x13, 0x2e, - 0x76, 0x6d, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x11, 0x2e, 0x76, 0x6d, 0x2e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x4d, 0x73, 0x67, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x43, 0x0a, 0x10, 0x41, - 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, - 0x17, 0x2e, 0x76, 0x6d, 0x2e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x46, - 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x12, 0x39, 0x0a, 0x0b, 0x41, 0x70, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x12, 0x2e, 0x76, 0x6d, 0x2e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x4d, 0x73, 0x67, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x35, 0x0a, 0x09, 0x41, - 0x70, 0x70, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x12, 0x10, 0x2e, 0x76, 0x6d, 0x2e, 0x41, 0x70, - 0x70, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x4d, 0x73, 0x67, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x12, 0x34, 0x0a, 0x06, 0x47, 0x61, 0x74, 0x68, 0x65, 0x72, 0x12, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x61, 0x74, 0x68, 0x65, 0x72, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x14, 0x43, 0x72, 0x6f, 0x73, - 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x1b, 0x2e, 0x76, 0x6d, 0x2e, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x73, 0x67, 0x1a, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x57, 0x0a, 0x1a, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, - 0x61, 0x69, 0x6e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x46, 0x61, 0x69, - 0x6c, 0x65, 0x64, 0x12, 0x21, 0x2e, 0x76, 0x6d, 0x2e, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, - 0x61, 0x69, 0x6e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x46, 0x61, 0x69, - 0x6c, 0x65, 0x64, 0x4d, 0x73, 0x67, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4d, - 0x0a, 0x15, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x41, 0x70, 0x70, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x2e, 0x76, 0x6d, 0x2e, 0x43, 0x72, 0x6f, - 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x4d, 0x73, 0x67, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x41, 0x0a, - 0x0c, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x17, 0x2e, - 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x41, - 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x50, 0x0a, 0x11, 0x42, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, 0x61, 0x72, 0x73, 0x65, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x1c, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, - 0x65, 0x64, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, - 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x11, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, - 0x1d, 0x2e, 0x76, 0x6d, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, - 0x0a, 0x12, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x41, 0x74, 0x48, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x12, 0x1d, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x49, 0x44, 0x41, 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x49, 0x44, 0x41, 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x10, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x79, 0x6e, 0x63, - 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x4c, 0x0a, 0x1d, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x73, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 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, 0x1b, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, + 0x76, 0x6d, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0x36, 0x0a, + 0x15, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6b, 0x73, 0x5f, 0x62, + 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x62, 0x6c, 0x6b, 0x73, + 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x35, 0x0a, 0x16, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, + 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x1b, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, + 0x6d, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0x31, 0x0a, 0x19, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x63, 0x63, 0x65, + 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x22, + 0xc5, 0x01, 0x0a, 0x1a, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, + 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, + 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x76, + 0x6d, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x63, + 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x6f, 0x64, + 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, 0x6d, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, + 0x03, 0x65, 0x72, 0x72, 0x22, 0x51, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x10, + 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x4b, 0x49, 0x50, 0x50, + 0x45, 0x44, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x54, 0x41, + 0x54, 0x49, 0x43, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x44, 0x59, + 0x4e, 0x41, 0x4d, 0x49, 0x43, 0x10, 0x03, 0x2a, 0x65, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x12, 0x15, 0x0a, 0x11, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, + 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x54, 0x41, 0x54, 0x45, + 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x49, 0x4e, 0x47, 0x10, 0x01, + 0x12, 0x17, 0x0a, 0x13, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x42, 0x4f, 0x4f, 0x54, 0x53, 0x54, + 0x52, 0x41, 0x50, 0x50, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x54, 0x41, + 0x54, 0x45, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x5f, 0x4f, 0x50, 0x10, 0x03, 0x2a, 0x61, + 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x41, 0x54, + 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, + 0x12, 0x15, 0x0a, 0x11, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x43, 0x45, + 0x53, 0x53, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x54, 0x41, 0x54, 0x55, + 0x53, 0x5f, 0x52, 0x45, 0x4a, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, + 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x45, 0x44, 0x10, + 0x03, 0x2a, 0x8e, 0x01, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x15, 0x0a, 0x11, 0x45, + 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x43, 0x4c, 0x4f, 0x53, + 0x45, 0x44, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4e, 0x4f, + 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x12, 0x21, 0x0a, 0x1d, 0x45, 0x52, 0x52, + 0x4f, 0x52, 0x5f, 0x48, 0x45, 0x49, 0x47, 0x48, 0x54, 0x5f, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x5f, + 0x49, 0x4e, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x03, 0x12, 0x24, 0x0a, 0x20, + 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x59, 0x4e, 0x43, + 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x45, 0x4d, 0x45, 0x4e, 0x54, 0x45, 0x44, + 0x10, 0x04, 0x32, 0xc1, 0x13, 0x0a, 0x02, 0x56, 0x4d, 0x12, 0x3b, 0x0a, 0x0a, 0x49, 0x6e, 0x69, + 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x12, 0x15, 0x2e, 0x76, 0x6d, 0x2e, 0x49, 0x6e, 0x69, + 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, + 0x2e, 0x76, 0x6d, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x53, 0x65, 0x74, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x12, 0x13, 0x2e, 0x76, 0x6d, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x76, 0x6d, 0x2e, 0x53, 0x65, 0x74, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, + 0x08, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x44, 0x0a, 0x0e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x76, 0x6d, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, + 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x50, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x48, + 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, - 0x1c, 0x2e, 0x76, 0x6d, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x45, 0x6e, - 0x61, 0x62, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, - 0x1a, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x53, 0x79, 0x6e, 0x63, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x16, 0x2e, 0x67, 0x6f, + 0x20, 0x2e, 0x76, 0x6d, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, + 0x63, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x39, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x14, + 0x2e, 0x76, 0x6d, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x0c, + 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x17, 0x2e, 0x76, + 0x6d, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3b, 0x0a, + 0x0a, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x15, 0x2e, 0x76, 0x6d, + 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x0a, 0x50, 0x61, + 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x15, 0x2e, 0x76, 0x6d, 0x2e, 0x50, 0x61, + 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x16, 0x2e, 0x76, 0x6d, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x12, 0x13, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, + 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, + 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, + 0x18, 0x2e, 0x76, 0x6d, 0x2e, 0x53, 0x65, 0x74, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, + 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x12, 0x34, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x1a, 0x26, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x67, 0x6f, - 0x69, 0x6e, 0x67, 0x53, 0x79, 0x6e, 0x63, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, - 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x13, 0x47, - 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, - 0x72, 0x79, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1f, 0x2e, 0x76, 0x6d, 0x2e, - 0x47, 0x65, 0x74, 0x4c, 0x61, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, - 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x11, 0x50, - 0x61, 0x72, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, - 0x12, 0x1c, 0x2e, 0x76, 0x6d, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, - 0x2e, 0x76, 0x6d, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, - 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, - 0x0f, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, - 0x12, 0x1a, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, - 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x76, - 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, - 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x12, 0x16, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x17, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, 0x65, 0x72, 0x69, 0x66, - 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x12, 0x16, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x70, 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x76, 0x6d, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x13, 0x2e, 0x76, 0x6d, 0x2e, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x37, 0x0a, 0x0a, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x11, 0x2e, + 0x76, 0x6d, 0x2e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x73, 0x67, + 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x43, 0x0a, 0x10, 0x41, 0x70, 0x70, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x17, 0x2e, 0x76, + 0x6d, 0x2e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x46, 0x61, 0x69, 0x6c, + 0x65, 0x64, 0x4d, 0x73, 0x67, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x39, 0x0a, + 0x0b, 0x41, 0x70, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x2e, 0x76, + 0x6d, 0x2e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x73, 0x67, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x16, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x52, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x35, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x47, + 0x6f, 0x73, 0x73, 0x69, 0x70, 0x12, 0x10, 0x2e, 0x76, 0x6d, 0x2e, 0x41, 0x70, 0x70, 0x47, 0x6f, + 0x73, 0x73, 0x69, 0x70, 0x4d, 0x73, 0x67, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, + 0x34, 0x0a, 0x06, 0x47, 0x61, 0x74, 0x68, 0x65, 0x72, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x1a, 0x12, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x61, 0x74, 0x68, 0x65, 0x72, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x14, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x2e, + 0x76, 0x6d, 0x2e, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x41, 0x70, 0x70, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x73, 0x67, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x12, 0x57, 0x0a, 0x1a, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, + 0x12, 0x21, 0x2e, 0x76, 0x6d, 0x2e, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, + 0x4d, 0x73, 0x67, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4d, 0x0a, 0x15, 0x43, + 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x2e, 0x76, 0x6d, 0x2e, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x41, 0x70, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, + 0x73, 0x67, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x41, 0x0a, 0x0c, 0x47, 0x65, + 0x74, 0x41, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x17, 0x2e, 0x76, 0x6d, 0x2e, + 0x47, 0x65, 0x74, 0x41, 0x6e, 0x63, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x63, 0x65, + 0x73, 0x74, 0x6f, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, + 0x11, 0x42, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x12, 0x1c, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, + 0x61, 0x72, 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1d, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x50, 0x61, 0x72, + 0x73, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x4a, 0x0a, 0x11, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x49, + 0x6e, 0x64, 0x65, 0x78, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1d, 0x2e, 0x76, + 0x6d, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x49, 0x6e, + 0x64, 0x65, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x12, 0x47, + 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x41, 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x12, 0x1d, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, + 0x44, 0x41, 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1e, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, + 0x41, 0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x48, 0x0a, 0x10, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x45, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x76, + 0x6d, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x45, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x1a, 0x47, 0x65, + 0x74, 0x4f, 0x6e, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x53, 0x79, 0x6e, 0x63, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x1a, 0x26, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x6e, 0x67, 0x6f, 0x69, 0x6e, 0x67, + 0x53, 0x79, 0x6e, 0x63, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x4c, + 0x61, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x53, 0x0a, 0x12, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x12, 0x1d, 0x2e, - 0x76, 0x6d, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x41, - 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x76, - 0x6d, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x63, - 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2d, 0x5a, 0x2b, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x76, 0x61, 0x2d, 0x6c, - 0x61, 0x62, 0x73, 0x2f, 0x61, 0x76, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x67, 0x6f, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x2f, 0x76, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1f, 0x2e, 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, + 0x4c, 0x61, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x11, 0x50, 0x61, 0x72, 0x73, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x1c, 0x2e, + 0x76, 0x6d, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, + 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x76, 0x6d, + 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, + 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x0f, 0x47, 0x65, + 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x1a, 0x2e, + 0x76, 0x6d, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, + 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x76, 0x6d, 0x2e, 0x47, + 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x15, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, + 0x6c, 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x21, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x61, 0x63, + 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x45, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0e, 0x42, 0x61, + 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x19, 0x2e, 0x76, + 0x6d, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x61, 0x63, + 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, 0x65, 0x72, 0x69, + 0x66, 0x79, 0x12, 0x16, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, 0x65, 0x72, + 0x69, 0x66, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x76, 0x6d, 0x2e, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x63, 0x63, 0x65, + 0x70, 0x74, 0x12, 0x16, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x41, 0x63, 0x63, + 0x65, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x6a, 0x65, 0x63, + 0x74, 0x12, 0x16, 0x2e, 0x76, 0x6d, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x6a, 0x65, + 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x12, 0x53, 0x0a, 0x12, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, + 0x79, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x12, 0x1d, 0x2e, 0x76, 0x6d, 0x2e, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x76, 0x6d, 0x2e, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x76, 0x61, 0x2d, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x61, 0x76, + 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, + 0x70, 0x62, 0x2f, 0x76, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3556,7 +3726,7 @@ func file_vm_vm_proto_rawDescGZIP() []byte { } var file_vm_vm_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_vm_vm_proto_msgTypes = make([]protoimpl.MessageInfo, 47) +var file_vm_vm_proto_msgTypes = make([]protoimpl.MessageInfo, 50) var file_vm_vm_proto_goTypes = []interface{}{ (State)(0), // 0: vm.State (Status)(0), // 1: vm.Status @@ -3607,112 +3777,121 @@ var file_vm_vm_proto_goTypes = []interface{}{ (*ParseStateSummaryResponse)(nil), // 46: vm.ParseStateSummaryResponse (*GetStateSummaryRequest)(nil), // 47: vm.GetStateSummaryRequest (*GetStateSummaryResponse)(nil), // 48: vm.GetStateSummaryResponse - (*StateSummaryAcceptRequest)(nil), // 49: vm.StateSummaryAcceptRequest - (*StateSummaryAcceptResponse)(nil), // 50: vm.StateSummaryAcceptResponse - (*timestamppb.Timestamp)(nil), // 51: google.protobuf.Timestamp - (*_go.MetricFamily)(nil), // 52: io.prometheus.client.MetricFamily - (*emptypb.Empty)(nil), // 53: google.protobuf.Empty + (*BackfillBlocksEnabledResponse)(nil), // 49: vm.BackfillBlocksEnabledResponse + (*BackfillBlocksRequest)(nil), // 50: vm.BackfillBlocksRequest + (*BackfillBlocksResponse)(nil), // 51: vm.BackfillBlocksResponse + (*StateSummaryAcceptRequest)(nil), // 52: vm.StateSummaryAcceptRequest + (*StateSummaryAcceptResponse)(nil), // 53: vm.StateSummaryAcceptResponse + (*timestamppb.Timestamp)(nil), // 54: google.protobuf.Timestamp + (*_go.MetricFamily)(nil), // 55: io.prometheus.client.MetricFamily + (*emptypb.Empty)(nil), // 56: google.protobuf.Empty } var file_vm_vm_proto_depIdxs = []int32{ 6, // 0: vm.InitializeRequest.db_servers:type_name -> vm.VersionedDBServer - 51, // 1: vm.InitializeResponse.timestamp:type_name -> google.protobuf.Timestamp + 54, // 1: vm.InitializeResponse.timestamp:type_name -> google.protobuf.Timestamp 0, // 2: vm.SetStateRequest.state:type_name -> vm.State - 51, // 3: vm.SetStateResponse.timestamp:type_name -> google.protobuf.Timestamp + 54, // 3: vm.SetStateResponse.timestamp:type_name -> google.protobuf.Timestamp 11, // 4: vm.CreateHandlersResponse.handlers:type_name -> vm.Handler 11, // 5: vm.CreateStaticHandlersResponse.handlers:type_name -> vm.Handler - 51, // 6: vm.BuildBlockResponse.timestamp:type_name -> google.protobuf.Timestamp + 54, // 6: vm.BuildBlockResponse.timestamp:type_name -> google.protobuf.Timestamp 1, // 7: vm.ParseBlockResponse.status:type_name -> vm.Status - 51, // 8: vm.ParseBlockResponse.timestamp:type_name -> google.protobuf.Timestamp + 54, // 8: vm.ParseBlockResponse.timestamp:type_name -> google.protobuf.Timestamp 1, // 9: vm.GetBlockResponse.status:type_name -> vm.Status - 51, // 10: vm.GetBlockResponse.timestamp:type_name -> google.protobuf.Timestamp + 54, // 10: vm.GetBlockResponse.timestamp:type_name -> google.protobuf.Timestamp 2, // 11: vm.GetBlockResponse.err:type_name -> vm.Error - 51, // 12: vm.BlockVerifyResponse.timestamp:type_name -> google.protobuf.Timestamp - 51, // 13: vm.AppRequestMsg.deadline:type_name -> google.protobuf.Timestamp - 51, // 14: vm.CrossChainAppRequestMsg.deadline:type_name -> google.protobuf.Timestamp + 54, // 12: vm.BlockVerifyResponse.timestamp:type_name -> google.protobuf.Timestamp + 54, // 13: vm.AppRequestMsg.deadline:type_name -> google.protobuf.Timestamp + 54, // 14: vm.CrossChainAppRequestMsg.deadline:type_name -> google.protobuf.Timestamp 15, // 15: vm.BatchedParseBlockResponse.response:type_name -> vm.ParseBlockResponse 2, // 16: vm.VerifyHeightIndexResponse.err:type_name -> vm.Error 2, // 17: vm.GetBlockIDAtHeightResponse.err:type_name -> vm.Error - 52, // 18: vm.GatherResponse.metric_families:type_name -> io.prometheus.client.MetricFamily + 55, // 18: vm.GatherResponse.metric_families:type_name -> io.prometheus.client.MetricFamily 2, // 19: vm.StateSyncEnabledResponse.err:type_name -> vm.Error 2, // 20: vm.GetOngoingSyncStateSummaryResponse.err:type_name -> vm.Error 2, // 21: vm.GetLastStateSummaryResponse.err:type_name -> vm.Error 2, // 22: vm.ParseStateSummaryResponse.err:type_name -> vm.Error 2, // 23: vm.GetStateSummaryResponse.err:type_name -> vm.Error - 3, // 24: vm.StateSummaryAcceptResponse.mode:type_name -> vm.StateSummaryAcceptResponse.Mode - 2, // 25: vm.StateSummaryAcceptResponse.err:type_name -> vm.Error - 4, // 26: vm.VM.Initialize:input_type -> vm.InitializeRequest - 7, // 27: vm.VM.SetState:input_type -> vm.SetStateRequest - 53, // 28: vm.VM.Shutdown:input_type -> google.protobuf.Empty - 53, // 29: vm.VM.CreateHandlers:input_type -> google.protobuf.Empty - 53, // 30: vm.VM.CreateStaticHandlers:input_type -> google.protobuf.Empty - 32, // 31: vm.VM.Connected:input_type -> vm.ConnectedRequest - 33, // 32: vm.VM.Disconnected:input_type -> vm.DisconnectedRequest - 12, // 33: vm.VM.BuildBlock:input_type -> vm.BuildBlockRequest - 14, // 34: vm.VM.ParseBlock:input_type -> vm.ParseBlockRequest - 16, // 35: vm.VM.GetBlock:input_type -> vm.GetBlockRequest - 18, // 36: vm.VM.SetPreference:input_type -> vm.SetPreferenceRequest - 53, // 37: vm.VM.Health:input_type -> google.protobuf.Empty - 53, // 38: vm.VM.Version:input_type -> google.protobuf.Empty - 25, // 39: vm.VM.AppRequest:input_type -> vm.AppRequestMsg - 26, // 40: vm.VM.AppRequestFailed:input_type -> vm.AppRequestFailedMsg - 27, // 41: vm.VM.AppResponse:input_type -> vm.AppResponseMsg - 28, // 42: vm.VM.AppGossip:input_type -> vm.AppGossipMsg - 53, // 43: vm.VM.Gather:input_type -> google.protobuf.Empty - 29, // 44: vm.VM.CrossChainAppRequest:input_type -> vm.CrossChainAppRequestMsg - 30, // 45: vm.VM.CrossChainAppRequestFailed:input_type -> vm.CrossChainAppRequestFailedMsg - 31, // 46: vm.VM.CrossChainAppResponse:input_type -> vm.CrossChainAppResponseMsg - 34, // 47: vm.VM.GetAncestors:input_type -> vm.GetAncestorsRequest - 36, // 48: vm.VM.BatchedParseBlock:input_type -> vm.BatchedParseBlockRequest - 53, // 49: vm.VM.VerifyHeightIndex:input_type -> google.protobuf.Empty - 39, // 50: vm.VM.GetBlockIDAtHeight:input_type -> vm.GetBlockIDAtHeightRequest - 53, // 51: vm.VM.StateSyncEnabled:input_type -> google.protobuf.Empty - 53, // 52: vm.VM.GetOngoingSyncStateSummary:input_type -> google.protobuf.Empty - 53, // 53: vm.VM.GetLastStateSummary:input_type -> google.protobuf.Empty - 45, // 54: vm.VM.ParseStateSummary:input_type -> vm.ParseStateSummaryRequest - 47, // 55: vm.VM.GetStateSummary:input_type -> vm.GetStateSummaryRequest - 19, // 56: vm.VM.BlockVerify:input_type -> vm.BlockVerifyRequest - 21, // 57: vm.VM.BlockAccept:input_type -> vm.BlockAcceptRequest - 22, // 58: vm.VM.BlockReject:input_type -> vm.BlockRejectRequest - 49, // 59: vm.VM.StateSummaryAccept:input_type -> vm.StateSummaryAcceptRequest - 5, // 60: vm.VM.Initialize:output_type -> vm.InitializeResponse - 8, // 61: vm.VM.SetState:output_type -> vm.SetStateResponse - 53, // 62: vm.VM.Shutdown:output_type -> google.protobuf.Empty - 9, // 63: vm.VM.CreateHandlers:output_type -> vm.CreateHandlersResponse - 10, // 64: vm.VM.CreateStaticHandlers:output_type -> vm.CreateStaticHandlersResponse - 53, // 65: vm.VM.Connected:output_type -> google.protobuf.Empty - 53, // 66: vm.VM.Disconnected:output_type -> google.protobuf.Empty - 13, // 67: vm.VM.BuildBlock:output_type -> vm.BuildBlockResponse - 15, // 68: vm.VM.ParseBlock:output_type -> vm.ParseBlockResponse - 17, // 69: vm.VM.GetBlock:output_type -> vm.GetBlockResponse - 53, // 70: vm.VM.SetPreference:output_type -> google.protobuf.Empty - 23, // 71: vm.VM.Health:output_type -> vm.HealthResponse - 24, // 72: vm.VM.Version:output_type -> vm.VersionResponse - 53, // 73: vm.VM.AppRequest:output_type -> google.protobuf.Empty - 53, // 74: vm.VM.AppRequestFailed:output_type -> google.protobuf.Empty - 53, // 75: vm.VM.AppResponse:output_type -> google.protobuf.Empty - 53, // 76: vm.VM.AppGossip:output_type -> google.protobuf.Empty - 41, // 77: vm.VM.Gather:output_type -> vm.GatherResponse - 53, // 78: vm.VM.CrossChainAppRequest:output_type -> google.protobuf.Empty - 53, // 79: vm.VM.CrossChainAppRequestFailed:output_type -> google.protobuf.Empty - 53, // 80: vm.VM.CrossChainAppResponse:output_type -> google.protobuf.Empty - 35, // 81: vm.VM.GetAncestors:output_type -> vm.GetAncestorsResponse - 37, // 82: vm.VM.BatchedParseBlock:output_type -> vm.BatchedParseBlockResponse - 38, // 83: vm.VM.VerifyHeightIndex:output_type -> vm.VerifyHeightIndexResponse - 40, // 84: vm.VM.GetBlockIDAtHeight:output_type -> vm.GetBlockIDAtHeightResponse - 42, // 85: vm.VM.StateSyncEnabled:output_type -> vm.StateSyncEnabledResponse - 43, // 86: vm.VM.GetOngoingSyncStateSummary:output_type -> vm.GetOngoingSyncStateSummaryResponse - 44, // 87: vm.VM.GetLastStateSummary:output_type -> vm.GetLastStateSummaryResponse - 46, // 88: vm.VM.ParseStateSummary:output_type -> vm.ParseStateSummaryResponse - 48, // 89: vm.VM.GetStateSummary:output_type -> vm.GetStateSummaryResponse - 20, // 90: vm.VM.BlockVerify:output_type -> vm.BlockVerifyResponse - 53, // 91: vm.VM.BlockAccept:output_type -> google.protobuf.Empty - 53, // 92: vm.VM.BlockReject:output_type -> google.protobuf.Empty - 50, // 93: vm.VM.StateSummaryAccept:output_type -> vm.StateSummaryAcceptResponse - 60, // [60:94] is the sub-list for method output_type - 26, // [26:60] is the sub-list for method input_type - 26, // [26:26] is the sub-list for extension type_name - 26, // [26:26] is the sub-list for extension extendee - 0, // [0:26] is the sub-list for field type_name + 2, // 24: vm.BackfillBlocksEnabledResponse.err:type_name -> vm.Error + 2, // 25: vm.BackfillBlocksResponse.err:type_name -> vm.Error + 3, // 26: vm.StateSummaryAcceptResponse.mode:type_name -> vm.StateSummaryAcceptResponse.Mode + 2, // 27: vm.StateSummaryAcceptResponse.err:type_name -> vm.Error + 4, // 28: vm.VM.Initialize:input_type -> vm.InitializeRequest + 7, // 29: vm.VM.SetState:input_type -> vm.SetStateRequest + 56, // 30: vm.VM.Shutdown:input_type -> google.protobuf.Empty + 56, // 31: vm.VM.CreateHandlers:input_type -> google.protobuf.Empty + 56, // 32: vm.VM.CreateStaticHandlers:input_type -> google.protobuf.Empty + 32, // 33: vm.VM.Connected:input_type -> vm.ConnectedRequest + 33, // 34: vm.VM.Disconnected:input_type -> vm.DisconnectedRequest + 12, // 35: vm.VM.BuildBlock:input_type -> vm.BuildBlockRequest + 14, // 36: vm.VM.ParseBlock:input_type -> vm.ParseBlockRequest + 16, // 37: vm.VM.GetBlock:input_type -> vm.GetBlockRequest + 18, // 38: vm.VM.SetPreference:input_type -> vm.SetPreferenceRequest + 56, // 39: vm.VM.Health:input_type -> google.protobuf.Empty + 56, // 40: vm.VM.Version:input_type -> google.protobuf.Empty + 25, // 41: vm.VM.AppRequest:input_type -> vm.AppRequestMsg + 26, // 42: vm.VM.AppRequestFailed:input_type -> vm.AppRequestFailedMsg + 27, // 43: vm.VM.AppResponse:input_type -> vm.AppResponseMsg + 28, // 44: vm.VM.AppGossip:input_type -> vm.AppGossipMsg + 56, // 45: vm.VM.Gather:input_type -> google.protobuf.Empty + 29, // 46: vm.VM.CrossChainAppRequest:input_type -> vm.CrossChainAppRequestMsg + 30, // 47: vm.VM.CrossChainAppRequestFailed:input_type -> vm.CrossChainAppRequestFailedMsg + 31, // 48: vm.VM.CrossChainAppResponse:input_type -> vm.CrossChainAppResponseMsg + 34, // 49: vm.VM.GetAncestors:input_type -> vm.GetAncestorsRequest + 36, // 50: vm.VM.BatchedParseBlock:input_type -> vm.BatchedParseBlockRequest + 56, // 51: vm.VM.VerifyHeightIndex:input_type -> google.protobuf.Empty + 39, // 52: vm.VM.GetBlockIDAtHeight:input_type -> vm.GetBlockIDAtHeightRequest + 56, // 53: vm.VM.StateSyncEnabled:input_type -> google.protobuf.Empty + 56, // 54: vm.VM.GetOngoingSyncStateSummary:input_type -> google.protobuf.Empty + 56, // 55: vm.VM.GetLastStateSummary:input_type -> google.protobuf.Empty + 45, // 56: vm.VM.ParseStateSummary:input_type -> vm.ParseStateSummaryRequest + 47, // 57: vm.VM.GetStateSummary:input_type -> vm.GetStateSummaryRequest + 56, // 58: vm.VM.BackfillBlocksEnabled:input_type -> google.protobuf.Empty + 50, // 59: vm.VM.BackfillBlocks:input_type -> vm.BackfillBlocksRequest + 19, // 60: vm.VM.BlockVerify:input_type -> vm.BlockVerifyRequest + 21, // 61: vm.VM.BlockAccept:input_type -> vm.BlockAcceptRequest + 22, // 62: vm.VM.BlockReject:input_type -> vm.BlockRejectRequest + 52, // 63: vm.VM.StateSummaryAccept:input_type -> vm.StateSummaryAcceptRequest + 5, // 64: vm.VM.Initialize:output_type -> vm.InitializeResponse + 8, // 65: vm.VM.SetState:output_type -> vm.SetStateResponse + 56, // 66: vm.VM.Shutdown:output_type -> google.protobuf.Empty + 9, // 67: vm.VM.CreateHandlers:output_type -> vm.CreateHandlersResponse + 10, // 68: vm.VM.CreateStaticHandlers:output_type -> vm.CreateStaticHandlersResponse + 56, // 69: vm.VM.Connected:output_type -> google.protobuf.Empty + 56, // 70: vm.VM.Disconnected:output_type -> google.protobuf.Empty + 13, // 71: vm.VM.BuildBlock:output_type -> vm.BuildBlockResponse + 15, // 72: vm.VM.ParseBlock:output_type -> vm.ParseBlockResponse + 17, // 73: vm.VM.GetBlock:output_type -> vm.GetBlockResponse + 56, // 74: vm.VM.SetPreference:output_type -> google.protobuf.Empty + 23, // 75: vm.VM.Health:output_type -> vm.HealthResponse + 24, // 76: vm.VM.Version:output_type -> vm.VersionResponse + 56, // 77: vm.VM.AppRequest:output_type -> google.protobuf.Empty + 56, // 78: vm.VM.AppRequestFailed:output_type -> google.protobuf.Empty + 56, // 79: vm.VM.AppResponse:output_type -> google.protobuf.Empty + 56, // 80: vm.VM.AppGossip:output_type -> google.protobuf.Empty + 41, // 81: vm.VM.Gather:output_type -> vm.GatherResponse + 56, // 82: vm.VM.CrossChainAppRequest:output_type -> google.protobuf.Empty + 56, // 83: vm.VM.CrossChainAppRequestFailed:output_type -> google.protobuf.Empty + 56, // 84: vm.VM.CrossChainAppResponse:output_type -> google.protobuf.Empty + 35, // 85: vm.VM.GetAncestors:output_type -> vm.GetAncestorsResponse + 37, // 86: vm.VM.BatchedParseBlock:output_type -> vm.BatchedParseBlockResponse + 38, // 87: vm.VM.VerifyHeightIndex:output_type -> vm.VerifyHeightIndexResponse + 40, // 88: vm.VM.GetBlockIDAtHeight:output_type -> vm.GetBlockIDAtHeightResponse + 42, // 89: vm.VM.StateSyncEnabled:output_type -> vm.StateSyncEnabledResponse + 43, // 90: vm.VM.GetOngoingSyncStateSummary:output_type -> vm.GetOngoingSyncStateSummaryResponse + 44, // 91: vm.VM.GetLastStateSummary:output_type -> vm.GetLastStateSummaryResponse + 46, // 92: vm.VM.ParseStateSummary:output_type -> vm.ParseStateSummaryResponse + 48, // 93: vm.VM.GetStateSummary:output_type -> vm.GetStateSummaryResponse + 49, // 94: vm.VM.BackfillBlocksEnabled:output_type -> vm.BackfillBlocksEnabledResponse + 51, // 95: vm.VM.BackfillBlocks:output_type -> vm.BackfillBlocksResponse + 20, // 96: vm.VM.BlockVerify:output_type -> vm.BlockVerifyResponse + 56, // 97: vm.VM.BlockAccept:output_type -> google.protobuf.Empty + 56, // 98: vm.VM.BlockReject:output_type -> google.protobuf.Empty + 53, // 99: vm.VM.StateSummaryAccept:output_type -> vm.StateSummaryAcceptResponse + 64, // [64:100] is the sub-list for method output_type + 28, // [28:64] is the sub-list for method input_type + 28, // [28:28] is the sub-list for extension type_name + 28, // [28:28] is the sub-list for extension extendee + 0, // [0:28] is the sub-list for field type_name } func init() { file_vm_vm_proto_init() } @@ -4262,7 +4441,7 @@ func file_vm_vm_proto_init() { } } file_vm_vm_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StateSummaryAcceptRequest); i { + switch v := v.(*BackfillBlocksEnabledResponse); i { case 0: return &v.state case 1: @@ -4274,6 +4453,42 @@ func file_vm_vm_proto_init() { } } file_vm_vm_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BackfillBlocksRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_vm_vm_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BackfillBlocksResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_vm_vm_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StateSummaryAcceptRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_vm_vm_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StateSummaryAcceptResponse); i { case 0: return &v.state @@ -4294,7 +4509,7 @@ func file_vm_vm_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_vm_vm_proto_rawDesc, NumEnums: 4, - NumMessages: 47, + NumMessages: 50, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/pb/vm/vm_grpc.pb.go b/proto/pb/vm/vm_grpc.pb.go index 5250af11f86f..6b5b048c7641 100644 --- a/proto/pb/vm/vm_grpc.pb.go +++ b/proto/pb/vm/vm_grpc.pb.go @@ -50,6 +50,8 @@ const ( VM_GetLastStateSummary_FullMethodName = "/vm.VM/GetLastStateSummary" VM_ParseStateSummary_FullMethodName = "/vm.VM/ParseStateSummary" VM_GetStateSummary_FullMethodName = "/vm.VM/GetStateSummary" + VM_BackfillBlocksEnabled_FullMethodName = "/vm.VM/BackfillBlocksEnabled" + VM_BackfillBlocks_FullMethodName = "/vm.VM/BackfillBlocks" VM_BlockVerify_FullMethodName = "/vm.VM/BlockVerify" VM_BlockAccept_FullMethodName = "/vm.VM/BlockAccept" VM_BlockReject_FullMethodName = "/vm.VM/BlockReject" @@ -125,6 +127,10 @@ type VMClient interface { // GetStateSummary retrieves the state summary that was generated at height // [summaryHeight]. GetStateSummary(ctx context.Context, in *GetStateSummaryRequest, opts ...grpc.CallOption) (*GetStateSummaryResponse, error) + // BackfillBlocksEnabled indicates whether the block backfilling is enabled for this VM. + BackfillBlocksEnabled(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*BackfillBlocksEnabledResponse, error) + // BackfillBlocks pushes to the VM downloaded blocks to be backfilled. + BackfillBlocks(ctx context.Context, in *BackfillBlocksRequest, opts ...grpc.CallOption) (*BackfillBlocksResponse, error) // Block BlockVerify(ctx context.Context, in *BlockVerifyRequest, opts ...grpc.CallOption) (*BlockVerifyResponse, error) BlockAccept(ctx context.Context, in *BlockAcceptRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) @@ -411,6 +417,24 @@ func (c *vMClient) GetStateSummary(ctx context.Context, in *GetStateSummaryReque return out, nil } +func (c *vMClient) BackfillBlocksEnabled(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*BackfillBlocksEnabledResponse, error) { + out := new(BackfillBlocksEnabledResponse) + err := c.cc.Invoke(ctx, VM_BackfillBlocksEnabled_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *vMClient) BackfillBlocks(ctx context.Context, in *BackfillBlocksRequest, opts ...grpc.CallOption) (*BackfillBlocksResponse, error) { + out := new(BackfillBlocksResponse) + err := c.cc.Invoke(ctx, VM_BackfillBlocks_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *vMClient) BlockVerify(ctx context.Context, in *BlockVerifyRequest, opts ...grpc.CallOption) (*BlockVerifyResponse, error) { out := new(BlockVerifyResponse) err := c.cc.Invoke(ctx, VM_BlockVerify_FullMethodName, in, out, opts...) @@ -516,6 +540,10 @@ type VMServer interface { // GetStateSummary retrieves the state summary that was generated at height // [summaryHeight]. GetStateSummary(context.Context, *GetStateSummaryRequest) (*GetStateSummaryResponse, error) + // BackfillBlocksEnabled indicates whether the block backfilling is enabled for this VM. + BackfillBlocksEnabled(context.Context, *emptypb.Empty) (*BackfillBlocksEnabledResponse, error) + // BackfillBlocks pushes to the VM downloaded blocks to be backfilled. + BackfillBlocks(context.Context, *BackfillBlocksRequest) (*BackfillBlocksResponse, error) // Block BlockVerify(context.Context, *BlockVerifyRequest) (*BlockVerifyResponse, error) BlockAccept(context.Context, *BlockAcceptRequest) (*emptypb.Empty, error) @@ -619,6 +647,12 @@ func (UnimplementedVMServer) ParseStateSummary(context.Context, *ParseStateSumma func (UnimplementedVMServer) GetStateSummary(context.Context, *GetStateSummaryRequest) (*GetStateSummaryResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetStateSummary not implemented") } +func (UnimplementedVMServer) BackfillBlocksEnabled(context.Context, *emptypb.Empty) (*BackfillBlocksEnabledResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method BackfillBlocksEnabled not implemented") +} +func (UnimplementedVMServer) BackfillBlocks(context.Context, *BackfillBlocksRequest) (*BackfillBlocksResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method BackfillBlocks not implemented") +} func (UnimplementedVMServer) BlockVerify(context.Context, *BlockVerifyRequest) (*BlockVerifyResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method BlockVerify not implemented") } @@ -1184,6 +1218,42 @@ func _VM_GetStateSummary_Handler(srv interface{}, ctx context.Context, dec func( return interceptor(ctx, in, info, handler) } +func _VM_BackfillBlocksEnabled_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(VMServer).BackfillBlocksEnabled(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: VM_BackfillBlocksEnabled_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(VMServer).BackfillBlocksEnabled(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _VM_BackfillBlocks_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BackfillBlocksRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(VMServer).BackfillBlocks(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: VM_BackfillBlocks_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(VMServer).BackfillBlocks(ctx, req.(*BackfillBlocksRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _VM_BlockVerify_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(BlockVerifyRequest) if err := dec(in); err != nil { @@ -1383,6 +1453,14 @@ var VM_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetStateSummary", Handler: _VM_GetStateSummary_Handler, }, + { + MethodName: "BackfillBlocksEnabled", + Handler: _VM_BackfillBlocksEnabled_Handler, + }, + { + MethodName: "BackfillBlocks", + Handler: _VM_BackfillBlocks_Handler, + }, { MethodName: "BlockVerify", Handler: _VM_BlockVerify_Handler, diff --git a/proto/vm/vm.proto b/proto/vm/vm.proto index 65e22df51848..84ff273b5ac3 100644 --- a/proto/vm/vm.proto +++ b/proto/vm/vm.proto @@ -80,6 +80,11 @@ service VM { // [summaryHeight]. rpc GetStateSummary(GetStateSummaryRequest) returns (GetStateSummaryResponse); + // BackfillBlocksEnabled indicates whether the block backfilling is enabled for this VM. + rpc BackfillBlocksEnabled(google.protobuf.Empty) returns (BackfillBlocksEnabledResponse); + // BackfillBlocks pushes to the VM downloaded blocks to be backfilled. + rpc BackfillBlocks(BackfillBlocksRequest) returns (BackfillBlocksResponse); + // Block rpc BlockVerify(BlockVerifyRequest) returns (BlockVerifyResponse); rpc BlockAccept(BlockAcceptRequest) returns (google.protobuf.Empty); @@ -396,6 +401,19 @@ message GetStateSummaryResponse { Error err = 3; } +message BackfillBlocksEnabledResponse { + bytes id = 1; + Error err = 2; +} + +message BackfillBlocksRequest { + repeated bytes blks_bytes = 1; +} + +message BackfillBlocksResponse { + Error err = 1; +} + message StateSummaryAcceptRequest { bytes bytes = 1; } diff --git a/snow/engine/snowman/block/mocks/state_syncable_vm.go b/snow/engine/snowman/block/mocks/state_syncable_vm.go index 50a1fe92e117..247afd11d355 100644 --- a/snow/engine/snowman/block/mocks/state_syncable_vm.go +++ b/snow/engine/snowman/block/mocks/state_syncable_vm.go @@ -11,6 +11,7 @@ import ( context "context" reflect "reflect" + ids "github.com/ava-labs/avalanchego/ids" block "github.com/ava-labs/avalanchego/snow/engine/snowman/block" gomock "go.uber.org/mock/gomock" ) @@ -38,6 +39,35 @@ func (m *MockStateSyncableVM) EXPECT() *MockStateSyncableVMMockRecorder { return m.recorder } +// BackfillBlocks mocks base method. +func (m *MockStateSyncableVM) BackfillBlocks(arg0 context.Context, arg1 [][]byte) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BackfillBlocks", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// BackfillBlocks indicates an expected call of BackfillBlocks. +func (mr *MockStateSyncableVMMockRecorder) BackfillBlocks(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BackfillBlocks", reflect.TypeOf((*MockStateSyncableVM)(nil).BackfillBlocks), arg0, arg1) +} + +// BackfillBlocksEnabled mocks base method. +func (m *MockStateSyncableVM) BackfillBlocksEnabled(arg0 context.Context) (ids.ID, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BackfillBlocksEnabled", arg0) + ret0, _ := ret[0].(ids.ID) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// BackfillBlocksEnabled indicates an expected call of BackfillBlocksEnabled. +func (mr *MockStateSyncableVMMockRecorder) BackfillBlocksEnabled(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BackfillBlocksEnabled", reflect.TypeOf((*MockStateSyncableVM)(nil).BackfillBlocksEnabled), arg0) +} + // GetLastStateSummary mocks base method. func (m *MockStateSyncableVM) GetLastStateSummary(arg0 context.Context) (block.StateSummary, error) { m.ctrl.T.Helper() diff --git a/snow/engine/snowman/block/state_syncable_vm.go b/snow/engine/snowman/block/state_syncable_vm.go index 5c25f37a7ad7..efce7243b78f 100644 --- a/snow/engine/snowman/block/state_syncable_vm.go +++ b/snow/engine/snowman/block/state_syncable_vm.go @@ -6,6 +6,8 @@ package block import ( "context" "errors" + + "github.com/ava-labs/avalanchego/ids" ) var ErrStateSyncableVMNotImplemented = errors.New("vm does not implement StateSyncableVM interface") @@ -42,4 +44,8 @@ type StateSyncableVM interface { // Returns database.ErrNotFound if no summary is available at // [summaryHeight]. GetStateSummary(ctx context.Context, summaryHeight uint64) (StateSummary, error) + + BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) + + BackfillBlocks(ctx context.Context, blocks [][]byte) error } diff --git a/snow/engine/snowman/block/test_state_syncable_vm.go b/snow/engine/snowman/block/test_state_syncable_vm.go index b05dd8118683..ffa08cac60d2 100644 --- a/snow/engine/snowman/block/test_state_syncable_vm.go +++ b/snow/engine/snowman/block/test_state_syncable_vm.go @@ -8,6 +8,7 @@ import ( "errors" "testing" + "github.com/ava-labs/avalanchego/ids" "github.com/stretchr/testify/require" ) @@ -19,6 +20,8 @@ var ( errGetLastStateSummary = errors.New("unexpectedly called GetLastStateSummary") errParseStateSummary = errors.New("unexpectedly called ParseStateSummary") errGetStateSummary = errors.New("unexpectedly called GetStateSummary") + errBackfillBlocksEnabled = errors.New("unexpectedly called BackfillBlocksEnabled") + errBackfillBlock = errors.New("unexpectedly called BackfillBlock") ) type TestStateSyncableVM struct { @@ -35,6 +38,9 @@ type TestStateSyncableVM struct { GetLastStateSummaryF func(context.Context) (StateSummary, error) ParseStateSummaryF func(ctx context.Context, summaryBytes []byte) (StateSummary, error) GetStateSummaryF func(ctx context.Context, summaryHeight uint64) (StateSummary, error) + + BackfillBlocksEnabledF func(context.Context) (ids.ID, error) + BackfillBlocksF func(context.Context, [][]byte) error } func (vm *TestStateSyncableVM) StateSyncEnabled(ctx context.Context) (bool, error) { @@ -86,3 +92,23 @@ func (vm *TestStateSyncableVM) GetStateSummary(ctx context.Context, summaryHeigh } return nil, errGetStateSummary } + +func (vm *TestStateSyncableVM) BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) { + if vm.BackfillBlocksEnabledF != nil { + return vm.BackfillBlocksEnabledF(ctx) + } + if vm.CantGetStateSummary && vm.T != nil { + require.FailNow(vm.T, errGetStateSummary.Error()) + } + return ids.Empty, errBackfillBlocksEnabled +} + +func (vm *TestStateSyncableVM) BackfillBlocks(ctx context.Context, blocks [][]byte) error { + if vm.BackfillBlocksF != nil { + return vm.BackfillBlocksF(ctx, blocks) + } + if vm.CantGetStateSummary && vm.T != nil { + require.FailNow(vm.T, errGetStateSummary.Error()) + } + return errBackfillBlock +} diff --git a/snow/engine/snowman/transitive.go b/snow/engine/snowman/transitive.go index d7889ede8ed0..d61e90c1ba23 100644 --- a/snow/engine/snowman/transitive.go +++ b/snow/engine/snowman/transitive.go @@ -420,6 +420,7 @@ func (t *Transitive) Start(ctx context.Context, startReqID uint32) error { return fmt.Errorf("failed to notify VM that consensus is starting: %w", err) } + return nil } diff --git a/vms/metervm/block_metrics.go b/vms/metervm/block_metrics.go index 094e41875aac..967e983b0f1d 100644 --- a/vms/metervm/block_metrics.go +++ b/vms/metervm/block_metrics.go @@ -43,7 +43,9 @@ type blockMetrics struct { parseStateSummary, parseStateSummaryErr, getStateSummary, - getStateSummaryErr metric.Averager + getStateSummaryErr, + backfillBlocksEnabled, + backfillBlocks metric.Averager } func (m *blockMetrics) Initialize( @@ -88,6 +90,8 @@ func (m *blockMetrics) Initialize( m.parseStateSummaryErr = newAverager(namespace, "parse_state_summary_err", reg, &errs) m.getStateSummary = newAverager(namespace, "get_state_summary", reg, &errs) m.getStateSummaryErr = newAverager(namespace, "get_state_summary_err", reg, &errs) + m.backfillBlocksEnabled = newAverager(namespace, "backfill_blocks_enabled", reg, &errs) + m.backfillBlocks = newAverager(namespace, "backfill_blocks", reg, &errs) } return errs.Err } diff --git a/vms/metervm/state_syncable_vm.go b/vms/metervm/state_syncable_vm.go index bcb27d682b08..6b37f29510fc 100644 --- a/vms/metervm/state_syncable_vm.go +++ b/vms/metervm/state_syncable_vm.go @@ -6,6 +6,7 @@ package metervm import ( "context" + "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow/engine/snowman/block" ) @@ -78,3 +79,37 @@ func (vm *blockVM) GetStateSummary(ctx context.Context, height uint64) (block.St vm.blockMetrics.getStateSummary.Observe(duration) return summary, nil } + +func (vm *blockVM) BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) { + if vm.ssVM == nil { + return ids.Empty, block.ErrStateSyncableVMNotImplemented + } + + start := vm.clock.Time() + blkID, err := vm.ssVM.BackfillBlocksEnabled(ctx) + end := vm.clock.Time() + duration := float64(end.Sub(start)) + if err != nil { + vm.blockMetrics.backfillBlocksEnabled.Observe(duration) + return ids.Empty, err + } + vm.blockMetrics.backfillBlocksEnabled.Observe(duration) + return blkID, nil +} + +func (vm *blockVM) BackfillBlocks(ctx context.Context, blocks [][]byte) error { + if vm.ssVM == nil { + return block.ErrStateSyncableVMNotImplemented + } + + start := vm.clock.Time() + err := vm.ssVM.BackfillBlocks(ctx, blocks) + end := vm.clock.Time() + duration := float64(end.Sub(start)) + if err != nil { + vm.blockMetrics.backfillBlocks.Observe(duration) + return err + } + vm.blockMetrics.backfillBlocks.Observe(duration) + return nil +} diff --git a/vms/proposervm/state_syncable_vm.go b/vms/proposervm/state_syncable_vm.go index da86d8c36e5c..5442ff8279d4 100644 --- a/vms/proposervm/state_syncable_vm.go +++ b/vms/proposervm/state_syncable_vm.go @@ -5,11 +5,13 @@ package proposervm import ( "context" + "errors" "fmt" "go.uber.org/zap" "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow/engine/snowman/block" "github.com/ava-labs/avalanchego/vms/proposervm/summary" ) @@ -159,3 +161,13 @@ func (vm *VM) buildStateSummary(ctx context.Context, innerSummary block.StateSum vm: vm, }, nil } + +var errNotYetImplemented = errors.New("backfilling not yet implemented") + +func (vm *VM) BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) { + return ids.Empty, errNotYetImplemented +} + +func (vm *VM) BackfillBlocks(ctx context.Context, blocks [][]byte) error { + return errNotYetImplemented +} diff --git a/vms/rpcchainvm/vm_client.go b/vms/rpcchainvm/vm_client.go index 5facd7208cb1..e289d67ccd65 100644 --- a/vms/rpcchainvm/vm_client.go +++ b/vms/rpcchainvm/vm_client.go @@ -820,6 +820,34 @@ func (vm *VMClient) GetStateSummary(ctx context.Context, summaryHeight uint64) ( }, err } +func (vm *VMClient) BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) { + resp, err := vm.client.BackfillBlocksEnabled(ctx, &emptypb.Empty{}) + if err != nil { + return ids.Empty, err + } + err = errEnumToError[resp.Err] + if err == block.ErrStateSyncableVMNotImplemented { + return ids.Empty, nil + } + return ids.ID(resp.Id), err +} + +func (vm *VMClient) BackfillBlocks(ctx context.Context, blocks [][]byte) error { + resp, err := vm.client.BackfillBlocks( + ctx, + &vmpb.BackfillBlocksRequest{ + BlksBytes: blocks, + }, + ) + if err != nil { + return err + } + if errEnum := resp.Err; errEnum != vmpb.Error_ERROR_UNSPECIFIED { + return errEnumToError[errEnum] + } + return nil +} + func (vm *VMClient) newBlockFromBuildBlock(resp *vmpb.BuildBlockResponse) (*blockClient, error) { id, err := ids.ToID(resp.Id) if err != nil { diff --git a/vms/rpcchainvm/vm_server.go b/vms/rpcchainvm/vm_server.go index ce800eae52d5..4fe4c7ee7851 100644 --- a/vms/rpcchainvm/vm_server.go +++ b/vms/rpcchainvm/vm_server.go @@ -827,6 +827,16 @@ func (vm *VMServer) GetStateSummary( }, nil } +var errNotYetImplemented = errors.New("backfilling not yet implemented") + +func (vm *VMServer) BackfillBlocksEnabled(context.Context, *emptypb.Empty) (*vmpb.BackfillBlocksEnabledResponse, error) { + return &vmpb.BackfillBlocksEnabledResponse{}, errNotYetImplemented +} + +func (vm *VMServer) BackfillBlocks(context.Context, *vmpb.BackfillBlocksRequest) (*vmpb.BackfillBlocksResponse, error) { + return &vmpb.BackfillBlocksResponse{}, errNotYetImplemented +} + func (vm *VMServer) BlockVerify(ctx context.Context, req *vmpb.BlockVerifyRequest) (*vmpb.BlockVerifyResponse, error) { blk, err := vm.vm.ParseBlock(ctx, req.Bytes) if err != nil { diff --git a/vms/tracedvm/block_vm.go b/vms/tracedvm/block_vm.go index b82466f3a420..9cd6266bebf9 100644 --- a/vms/tracedvm/block_vm.go +++ b/vms/tracedvm/block_vm.go @@ -59,6 +59,8 @@ type blockVM struct { getLastStateSummaryTag string parseStateSummaryTag string getStateSummaryTag string + backfillBlocksEnabledTag string + backfillBlocksTag string tracer trace.Tracer } diff --git a/vms/tracedvm/state_syncable_vm.go b/vms/tracedvm/state_syncable_vm.go index 75738462368b..e9f6f98bb019 100644 --- a/vms/tracedvm/state_syncable_vm.go +++ b/vms/tracedvm/state_syncable_vm.go @@ -10,6 +10,7 @@ import ( oteltrace "go.opentelemetry.io/otel/trace" + "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow/engine/snowman/block" ) @@ -71,3 +72,27 @@ func (vm *blockVM) GetStateSummary(ctx context.Context, height uint64) (block.St return vm.ssVM.GetStateSummary(ctx, height) } + +func (vm *blockVM) BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) { + if vm.ssVM == nil { + return ids.Empty, block.ErrStateSyncableVMNotImplemented + } + + ctx, span := vm.tracer.Start(ctx, vm.backfillBlocksEnabledTag) + defer span.End() + + return vm.ssVM.BackfillBlocksEnabled(ctx) +} + +func (vm *blockVM) BackfillBlocks(ctx context.Context, blocks [][]byte) error { + if vm.ssVM == nil { + return block.ErrStateSyncableVMNotImplemented + } + + ctx, span := vm.tracer.Start(ctx, vm.backfillBlocksTag, oteltrace.WithAttributes( + attribute.Int("blocksCount", len(blocks)), + )) + defer span.End() + + return vm.ssVM.BackfillBlocks(ctx, blocks) +} From 6fbe978a07b85d480a1a0bdb5dd0a36cdbf10d72 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 5 Oct 2023 22:33:18 +0200 Subject: [PATCH 02/36] bumped coreth version --- go.mod | 2 +- go.sum | 4 ++-- snow/engine/snowman/block/test_state_syncable_vm.go | 3 ++- vms/proposervm/state_syncable_vm.go | 4 ++-- vms/rpcchainvm/vm_server.go | 4 ++-- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index fd3f1e144537..4402a6da6747 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/DataDog/zstd v1.5.2 github.com/Microsoft/go-winio v0.5.2 github.com/NYTimes/gziphandler v1.1.1 - github.com/ava-labs/coreth v0.12.5-rc.6 + github.com/ava-labs/coreth v0.12.6-0.20231005200132-6e8d83b838d2 github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 github.com/btcsuite/btcd/btcutil v1.1.3 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 diff --git a/go.sum b/go.sum index 914507ff2a20..da8fab94fb1f 100644 --- a/go.sum +++ b/go.sum @@ -61,8 +61,8 @@ github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/ava-labs/coreth v0.12.5-rc.6 h1:OajGUyKkO5Q82XSuMa8T5UD6QywtCHUiZ4Tv3RFmRBU= -github.com/ava-labs/coreth v0.12.5-rc.6/go.mod h1:s5wVyy+5UCCk2m0Tq3jVmy0UqOpKBDYqRE13gInCJVs= +github.com/ava-labs/coreth v0.12.6-0.20231005200132-6e8d83b838d2 h1:+1GOlSwwflM+3TAsYBlopSRgC/JSmLXO7ncoR3V5Ofw= +github.com/ava-labs/coreth v0.12.6-0.20231005200132-6e8d83b838d2/go.mod h1:Hrw3vhUa/KSusUN2JnwFdlwh3vIfjH7pK26TkekoKYc= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 h1:EdxD90j5sClfL5Ngpz2TlnbnkNYdFPDXa0jDOjam65c= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7/go.mod h1:XhiXSrh90sHUbkERzaxEftCmUz53eCijshDLZ4fByVM= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= diff --git a/snow/engine/snowman/block/test_state_syncable_vm.go b/snow/engine/snowman/block/test_state_syncable_vm.go index ffa08cac60d2..e67581bcbd99 100644 --- a/snow/engine/snowman/block/test_state_syncable_vm.go +++ b/snow/engine/snowman/block/test_state_syncable_vm.go @@ -8,8 +8,9 @@ import ( "errors" "testing" - "github.com/ava-labs/avalanchego/ids" "github.com/stretchr/testify/require" + + "github.com/ava-labs/avalanchego/ids" ) var ( diff --git a/vms/proposervm/state_syncable_vm.go b/vms/proposervm/state_syncable_vm.go index 5442ff8279d4..02f0f4694ee5 100644 --- a/vms/proposervm/state_syncable_vm.go +++ b/vms/proposervm/state_syncable_vm.go @@ -164,10 +164,10 @@ func (vm *VM) buildStateSummary(ctx context.Context, innerSummary block.StateSum var errNotYetImplemented = errors.New("backfilling not yet implemented") -func (vm *VM) BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) { +func (*VM) BackfillBlocksEnabled(context.Context) (ids.ID, error) { return ids.Empty, errNotYetImplemented } -func (vm *VM) BackfillBlocks(ctx context.Context, blocks [][]byte) error { +func (*VM) BackfillBlocks(context.Context, [][]byte) error { return errNotYetImplemented } diff --git a/vms/rpcchainvm/vm_server.go b/vms/rpcchainvm/vm_server.go index 4fe4c7ee7851..4fc34e1eff50 100644 --- a/vms/rpcchainvm/vm_server.go +++ b/vms/rpcchainvm/vm_server.go @@ -829,11 +829,11 @@ func (vm *VMServer) GetStateSummary( var errNotYetImplemented = errors.New("backfilling not yet implemented") -func (vm *VMServer) BackfillBlocksEnabled(context.Context, *emptypb.Empty) (*vmpb.BackfillBlocksEnabledResponse, error) { +func (*VMServer) BackfillBlocksEnabled(context.Context, *emptypb.Empty) (*vmpb.BackfillBlocksEnabledResponse, error) { return &vmpb.BackfillBlocksEnabledResponse{}, errNotYetImplemented } -func (vm *VMServer) BackfillBlocks(context.Context, *vmpb.BackfillBlocksRequest) (*vmpb.BackfillBlocksResponse, error) { +func (*VMServer) BackfillBlocks(context.Context, *vmpb.BackfillBlocksRequest) (*vmpb.BackfillBlocksResponse, error) { return &vmpb.BackfillBlocksResponse{}, errNotYetImplemented } From 5025fcfd32cbd462225394c2fd72e0c346558818 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 26 Oct 2023 14:49:15 +0200 Subject: [PATCH 03/36] temporarily cut coreth dependency --- go.mod | 25 - go.sum | 76 -- node/node.go | 4 +- tests/e2e/c/dynamic_fees.go | 328 ++++---- tests/e2e/c/interchain_workflow.go | 322 +++---- tests/e2e/e2e.go | 124 +-- tests/e2e/p/interchain_workflow.go | 446 +++++----- tests/e2e/x/interchain_workflow.go | 298 +++---- tests/fixture/testnet/config.go | 56 +- vms/example/xsvm/cmd/chain/create/cmd.go | 6 +- wallet/chain/c/backend.go | 300 +++---- wallet/chain/c/builder.go | 792 +++++++++--------- wallet/chain/c/builder_with_options.go | 136 +-- wallet/chain/c/context.go | 130 +-- wallet/chain/c/signer.go | 436 +++++----- wallet/chain/c/wallet.go | 402 ++++----- wallet/chain/c/wallet_with_options.go | 134 +-- wallet/subnet/primary/api.go | 123 +-- wallet/subnet/primary/example_test.go | 2 +- .../add-permissioned-subnet-validator/main.go | 6 +- .../examples/add-primary-validator/main.go | 2 +- .../primary/examples/c-chain-export/main.go | 118 +-- .../primary/examples/c-chain-import/main.go | 126 +-- .../primary/examples/create-asset/main.go | 2 +- .../primary/examples/create-chain/main.go | 6 +- .../examples/create-locked-stakeable/main.go | 2 +- .../primary/examples/create-subnet/main.go | 2 +- .../examples/remove-subnet-validator/main.go | 6 +- wallet/subnet/primary/wallet.go | 43 +- 29 files changed, 2178 insertions(+), 2275 deletions(-) diff --git a/go.mod b/go.mod index f351efbef090..40d59d0cb294 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,6 @@ require ( github.com/DataDog/zstd v1.5.2 github.com/Microsoft/go-winio v0.5.2 github.com/NYTimes/gziphandler v1.1.1 - github.com/ava-labs/coreth v0.12.7-rc.1 github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 github.com/btcsuite/btcd/btcutil v1.1.3 github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 @@ -72,7 +71,6 @@ require ( require ( github.com/BurntSushi/toml v1.2.1 // indirect - github.com/VictoriaMetrics/fastcache v1.10.0 // indirect github.com/benbjohnson/clock v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect @@ -81,44 +79,26 @@ require ( github.com/cockroachdb/errors v1.9.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/redact v1.1.3 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/deckarep/golang-set/v2 v2.1.0 // indirect - github.com/dlclark/regexp2 v1.7.0 // indirect - github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect - github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/frankban/quicktest v1.14.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect - github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect - github.com/go-stack/stack v1.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect - github.com/google/uuid v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 // indirect - github.com/hashicorp/go-bexpr v0.1.10 // indirect - github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/klauspost/compress v1.15.15 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/magiconair/properties v1.8.6 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/mitchellh/pointerstructure v1.2.0 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect @@ -126,17 +106,12 @@ require ( github.com/prometheus/common v0.39.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sanity-io/litter v1.5.1 // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/status-im/keycard-go v0.2.0 // indirect github.com/subosito/gotenv v1.3.0 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect - github.com/tyler-smith/go-bip39 v1.1.0 // indirect - github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa // indirect - github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/zondax/hid v0.9.1 // indirect github.com/zondax/ledger-go v0.14.1 // indirect diff --git a/go.sum b/go.sum index d301d4b6be81..09e5526b3f20 100644 --- a/go.sum +++ b/go.sum @@ -52,18 +52,12 @@ github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cq github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= -github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY= -github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/ava-labs/coreth v0.12.7-rc.1 h1:fvjow2Jqkq1RNtW4v2Kx0DdTVp+3+fCY421TxpDDRfM= -github.com/ava-labs/coreth v0.12.7-rc.1/go.mod h1:sNbwitXv4AhLvWpSqy6V8yzkhGFeWBQFD31/xiRDJ5M= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 h1:EdxD90j5sClfL5Ngpz2TlnbnkNYdFPDXa0jDOjam65c= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7/go.mod h1:XhiXSrh90sHUbkERzaxEftCmUz53eCijshDLZ4fByVM= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= @@ -100,18 +94,13 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -141,16 +130,12 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= -github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= @@ -161,14 +146,6 @@ github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6ps github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= -github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= -github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= -github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= -github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -185,8 +162,6 @@ github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2 github.com/ethereum/go-ethereum v1.12.0/go.mod h1:/oo2X/dZLJjf2mJ6YT9wcWxa4nNJDBKDBU6sFIpx1Gs= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -195,8 +170,6 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= @@ -220,11 +193,7 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= -github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= @@ -309,14 +278,10 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -337,17 +302,11 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 h1:kr3j8iIMR4ywO/O0rvksXaJvauGGCMg2zAZIiNZ9uIQ= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0/go.mod h1:ummNFgdgLhhX7aIiy35vVmQNS0rWXknfPE0qe6fmFXg= -github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= -github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e/go.mod h1:j9cQbcqHQujT0oKJ38PylVfqohClLr3CvDC+Qcg+lhU= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8= @@ -359,7 +318,6 @@ github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3 github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -401,7 +359,6 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -409,7 +366,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= @@ -420,17 +376,11 @@ github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -439,11 +389,8 @@ github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= -github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -462,8 +409,6 @@ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -531,8 +476,6 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sanity-io/litter v1.5.1 h1:dwnrSypP6q56o3lFxTU+t2fwQ9A+U5qrXVO4Qg9KwVU= github.com/sanity-io/litter v1.5.1/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0= @@ -568,8 +511,6 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= -github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= -github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -599,14 +540,10 @@ github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITn github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= -github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -618,8 +555,6 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1: github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= @@ -629,7 +564,6 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= @@ -727,7 +661,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -773,7 +706,6 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -797,7 +729,6 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -862,12 +793,8 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -884,7 +811,6 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -948,7 +874,6 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1073,7 +998,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= diff --git a/node/node.go b/node/node.go index 4200a33699ab..9e72b7dcc450 100644 --- a/node/node.go +++ b/node/node.go @@ -24,7 +24,7 @@ import ( "go.uber.org/zap" - coreth "github.com/ava-labs/coreth/plugin/evm" + // coreth "github.com/ava-labs/coreth/plugin/evm" "github.com/ava-labs/avalanchego/api/admin" "github.com/ava-labs/avalanchego/api/auth" @@ -935,7 +935,7 @@ func (n *Node) initVMs() error { CreateAssetTxFee: n.Config.CreateAssetTxFee, }, }), - vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), + // vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), n.VMManager.RegisterFactory(context.TODO(), secp256k1fx.ID, &secp256k1fx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), nftfx.ID, &nftfx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), propertyfx.ID, &propertyfx.Factory{}), diff --git a/tests/e2e/c/dynamic_fees.go b/tests/e2e/c/dynamic_fees.go index f3a1daaf3d2c..4234c170af6f 100644 --- a/tests/e2e/c/dynamic_fees.go +++ b/tests/e2e/c/dynamic_fees.go @@ -3,167 +3,167 @@ package c -import ( - "math/big" - "strings" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/stretchr/testify/require" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/coreth/core/types" - "github.com/ava-labs/coreth/params" - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/tests" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/tests/fixture/testnet" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -) - -// This test uses the compiled bin for `hashing.sol` as -// well as its ABI contained in `hashing_contract.go`. - -var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { - require := require.New(ginkgo.GinkgoT()) - - // Need a gas limit much larger than the standard 21_000 to enable - // the contract to induce a gas price increase - const largeGasLimit = uint64(8_000_000) - - // TODO(marun) What is the significance of this value? - gasTip := big.NewInt(1000 * params.GWei) - - ginkgo.It("should ensure that the gas price is affected by load", func() { - ginkgo.By("creating a new private network to ensure isolation from other tests") - privateNetwork := e2e.Env.NewPrivateNetwork() - - ginkgo.By("allocating a pre-funded key") - key := privateNetwork.GetConfig().FundedKeys[0] - ethAddress := evm.GetEthAddress(key) - - ginkgo.By("initializing a coreth client") - node := privateNetwork.GetNodes()[0] - nodeURI := testnet.NodeURI{ - NodeID: node.GetID(), - URI: node.GetProcessContext().URI, - } - ethClient := e2e.Env.NewEthClient(nodeURI) - - ginkgo.By("initializing a transaction signer") - cChainID, err := ethClient.ChainID(e2e.DefaultContext()) - require.NoError(err) - signer := types.NewEIP155Signer(cChainID) - ecdsaKey := key.ToECDSA() - sign := func(tx *types.Transaction) *types.Transaction { - signedTx, err := types.SignTx(tx, signer, ecdsaKey) - require.NoError(err) - return signedTx - } - - var contractAddress common.Address - ginkgo.By("deploying an expensive contract", func() { - // Create transaction - nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) - require.NoError(err) - compiledContract := common.Hex2Bytes(hashingCompiledContract) - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - GasPrice: gasTip, - Gas: largeGasLimit, - Value: common.Big0, - Data: compiledContract, - }) - - // Send the transaction and wait for acceptance - signedTx := sign(tx) - receipt := e2e.SendEthTransaction(ethClient, signedTx) - - contractAddress = receipt.ContractAddress - }) - - var gasPrice *big.Int - ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { - // Evaluate the bytes representation of the contract - hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) - require.NoError(err) - contractData, err := hashingABI.Pack("hashIt") - require.NoError(err) - - var initialGasPrice *big.Int - e2e.Eventually(func() bool { - // Check the gas price - var err error - gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) - require.NoError(err) - if initialGasPrice == nil { - initialGasPrice = gasPrice - tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) - } else if gasPrice.Cmp(initialGasPrice) > 0 { - // Gas price has increased - tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) - return true - } - - // Create the transaction - nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) - require.NoError(err) - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - GasPrice: gasTip, - Gas: largeGasLimit, - To: &contractAddress, - Value: common.Big0, - Data: contractData, - }) - - // Send the transaction and wait for acceptance - signedTx := sign(tx) - _ = e2e.SendEthTransaction(ethClient, signedTx) - - // The gas price will be checked at the start of the next iteration - return false - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") - }) - - ginkgo.By("waiting for the gas price to decrease...", func() { - initialGasPrice := gasPrice - e2e.Eventually(func() bool { - var err error - gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) - require.NoError(err) - tests.Outf("{{blue}}.{{/}}") - return initialGasPrice.Cmp(gasPrice) > 0 - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") - tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) - }) - - ginkgo.By("sending funds at the current gas price", func() { - // Create a recipient address - factory := secp256k1.Factory{} - recipientKey, err := factory.NewPrivateKey() - require.NoError(err) - recipientEthAddress := evm.GetEthAddress(recipientKey) - - // Create transaction - nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) - require.NoError(err) - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - GasPrice: gasPrice, - Gas: e2e.DefaultGasLimit, - To: &recipientEthAddress, - Value: common.Big0, - }) - - // Send the transaction and wait for acceptance - signedTx := sign(tx) - _ = e2e.SendEthTransaction(ethClient, signedTx) - }) - - e2e.CheckBootstrapIsPossible(privateNetwork) - }) -}) +// import ( +// "math/big" +// "strings" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/stretchr/testify/require" + +// "github.com/ethereum/go-ethereum/accounts/abi" +// "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/coreth/core/types" +// "github.com/ava-labs/coreth/params" +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/tests" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/tests/fixture/testnet" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// ) + +// // This test uses the compiled bin for `hashing.sol` as +// // well as its ABI contained in `hashing_contract.go`. + +// var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { +// require := require.New(ginkgo.GinkgoT()) + +// // Need a gas limit much larger than the standard 21_000 to enable +// // the contract to induce a gas price increase +// const largeGasLimit = uint64(8_000_000) + +// // TODO(marun) What is the significance of this value? +// gasTip := big.NewInt(1000 * params.GWei) + +// ginkgo.It("should ensure that the gas price is affected by load", func() { +// ginkgo.By("creating a new private network to ensure isolation from other tests") +// privateNetwork := e2e.Env.NewPrivateNetwork() + +// ginkgo.By("allocating a pre-funded key") +// key := privateNetwork.GetConfig().FundedKeys[0] +// ethAddress := evm.GetEthAddress(key) + +// ginkgo.By("initializing a coreth client") +// node := privateNetwork.GetNodes()[0] +// nodeURI := testnet.NodeURI{ +// NodeID: node.GetID(), +// URI: node.GetProcessContext().URI, +// } +// ethClient := e2e.Env.NewEthClient(nodeURI) + +// ginkgo.By("initializing a transaction signer") +// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) +// require.NoError(err) +// signer := types.NewEIP155Signer(cChainID) +// ecdsaKey := key.ToECDSA() +// sign := func(tx *types.Transaction) *types.Transaction { +// signedTx, err := types.SignTx(tx, signer, ecdsaKey) +// require.NoError(err) +// return signedTx +// } + +// var contractAddress common.Address +// ginkgo.By("deploying an expensive contract", func() { +// // Create transaction +// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) +// require.NoError(err) +// compiledContract := common.Hex2Bytes(hashingCompiledContract) +// tx := types.NewTx(&types.LegacyTx{ +// Nonce: nonce, +// GasPrice: gasTip, +// Gas: largeGasLimit, +// Value: common.Big0, +// Data: compiledContract, +// }) + +// // Send the transaction and wait for acceptance +// signedTx := sign(tx) +// receipt := e2e.SendEthTransaction(ethClient, signedTx) + +// contractAddress = receipt.ContractAddress +// }) + +// var gasPrice *big.Int +// ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { +// // Evaluate the bytes representation of the contract +// hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) +// require.NoError(err) +// contractData, err := hashingABI.Pack("hashIt") +// require.NoError(err) + +// var initialGasPrice *big.Int +// e2e.Eventually(func() bool { +// // Check the gas price +// var err error +// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) +// require.NoError(err) +// if initialGasPrice == nil { +// initialGasPrice = gasPrice +// tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) +// } else if gasPrice.Cmp(initialGasPrice) > 0 { +// // Gas price has increased +// tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) +// return true +// } + +// // Create the transaction +// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) +// require.NoError(err) +// tx := types.NewTx(&types.LegacyTx{ +// Nonce: nonce, +// GasPrice: gasTip, +// Gas: largeGasLimit, +// To: &contractAddress, +// Value: common.Big0, +// Data: contractData, +// }) + +// // Send the transaction and wait for acceptance +// signedTx := sign(tx) +// _ = e2e.SendEthTransaction(ethClient, signedTx) + +// // The gas price will be checked at the start of the next iteration +// return false +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") +// }) + +// ginkgo.By("waiting for the gas price to decrease...", func() { +// initialGasPrice := gasPrice +// e2e.Eventually(func() bool { +// var err error +// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) +// require.NoError(err) +// tests.Outf("{{blue}}.{{/}}") +// return initialGasPrice.Cmp(gasPrice) > 0 +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") +// tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) +// }) + +// ginkgo.By("sending funds at the current gas price", func() { +// // Create a recipient address +// factory := secp256k1.Factory{} +// recipientKey, err := factory.NewPrivateKey() +// require.NoError(err) +// recipientEthAddress := evm.GetEthAddress(recipientKey) + +// // Create transaction +// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) +// require.NoError(err) +// tx := types.NewTx(&types.LegacyTx{ +// Nonce: nonce, +// GasPrice: gasPrice, +// Gas: e2e.DefaultGasLimit, +// To: &recipientEthAddress, +// Value: common.Big0, +// }) + +// // Send the transaction and wait for acceptance +// signedTx := sign(tx) +// _ = e2e.SendEthTransaction(ethClient, signedTx) +// }) + +// e2e.CheckBootstrapIsPossible(privateNetwork) +// }) +// }) diff --git a/tests/e2e/c/interchain_workflow.go b/tests/e2e/c/interchain_workflow.go index 47c430d4c12a..a072596e1dc9 100644 --- a/tests/e2e/c/interchain_workflow.go +++ b/tests/e2e/c/interchain_workflow.go @@ -3,164 +3,164 @@ package c -import ( - "math/big" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/coreth/core/types" - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { - require := require.New(ginkgo.GinkgoT()) - - const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer - - ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { - ginkgo.By("initializing a new eth client") - // Select a random node URI to use for both the eth client and - // the wallet to avoid having to verify that all nodes are at - // the same height before initializing the wallet. - nodeURI := e2e.Env.GetRandomNodeURI() - ethClient := e2e.Env.NewEthClient(nodeURI) - - ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") - senderKey := e2e.Env.AllocateFundedKey() - senderEthAddress := evm.GetEthAddress(senderKey) - factory := secp256k1.Factory{} - recipientKey, err := factory.NewPrivateKey() - require.NoError(err) - recipientEthAddress := evm.GetEthAddress(recipientKey) - - ginkgo.By("sending funds from one address to another on the C-Chain", func() { - // Create transaction - acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) - require.NoError(err) - gasPrice := e2e.SuggestGasPrice(ethClient) - tx := types.NewTransaction( - acceptedNonce, - recipientEthAddress, - big.NewInt(int64(txAmount)), - e2e.DefaultGasLimit, - gasPrice, - nil, - ) - - // Sign transaction - cChainID, err := ethClient.ChainID(e2e.DefaultContext()) - require.NoError(err) - signer := types.NewEIP155Signer(cChainID) - signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) - require.NoError(err) - - _ = e2e.SendEthTransaction(ethClient, signedTx) - - ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") - e2e.Eventually(func() bool { - balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) - require.NoError(err) - return balance.Cmp(big.NewInt(0)) > 0 - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") - }) - - // Wallet must be initialized after sending funds on the - // C-Chain with the same node URI to ensure wallet state - // matches on-chain state. - ginkgo.By("initializing a keychain and associated wallet") - keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) - baseWallet := e2e.Env.NewWallet(keychain, nodeURI) - xWallet := baseWallet.X() - cWallet := baseWallet.C() - pWallet := baseWallet.P() - - ginkgo.By("defining common configuration") - avaxAssetID := xWallet.AVAXAssetID() - // Use the same owner for import funds to X-Chain and P-Chain - recipientOwner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - recipientKey.Address(), - }, - } - // Use the same outputs for both X-Chain and P-Chain exports - exportOutputs := []*secp256k1fx.TransferOutput{ - { - Amt: txAmount, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - keychain.Keys[0].Address(), - }, - }, - }, - } - - ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { - _, err := cWallet.IssueExportTx( - xWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { - _, err := xWallet.IssueImportTx( - cWallet.BlockchainID(), - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { - balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { - _, err := cWallet.IssueExportTx( - constants.PlatformChainID, - exportOutputs, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { - _, err = pWallet.IssueImportTx( - cWallet.BlockchainID(), - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { - balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) - }) -}) +// import ( +// "math/big" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/stretchr/testify/require" + +// "github.com/ava-labs/coreth/core/types" +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { +// require := require.New(ginkgo.GinkgoT()) + +// const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer + +// ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { +// ginkgo.By("initializing a new eth client") +// // Select a random node URI to use for both the eth client and +// // the wallet to avoid having to verify that all nodes are at +// // the same height before initializing the wallet. +// nodeURI := e2e.Env.GetRandomNodeURI() +// ethClient := e2e.Env.NewEthClient(nodeURI) + +// ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") +// senderKey := e2e.Env.AllocateFundedKey() +// senderEthAddress := evm.GetEthAddress(senderKey) +// factory := secp256k1.Factory{} +// recipientKey, err := factory.NewPrivateKey() +// require.NoError(err) +// recipientEthAddress := evm.GetEthAddress(recipientKey) + +// ginkgo.By("sending funds from one address to another on the C-Chain", func() { +// // Create transaction +// acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) +// require.NoError(err) +// gasPrice := e2e.SuggestGasPrice(ethClient) +// tx := types.NewTransaction( +// acceptedNonce, +// recipientEthAddress, +// big.NewInt(int64(txAmount)), +// e2e.DefaultGasLimit, +// gasPrice, +// nil, +// ) + +// // Sign transaction +// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) +// require.NoError(err) +// signer := types.NewEIP155Signer(cChainID) +// signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) +// require.NoError(err) + +// _ = e2e.SendEthTransaction(ethClient, signedTx) + +// ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") +// e2e.Eventually(func() bool { +// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) +// require.NoError(err) +// return balance.Cmp(big.NewInt(0)) > 0 +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") +// }) + +// // Wallet must be initialized after sending funds on the +// // C-Chain with the same node URI to ensure wallet state +// // matches on-chain state. +// ginkgo.By("initializing a keychain and associated wallet") +// keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) +// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) +// xWallet := baseWallet.X() +// cWallet := baseWallet.C() +// pWallet := baseWallet.P() + +// ginkgo.By("defining common configuration") +// avaxAssetID := xWallet.AVAXAssetID() +// // Use the same owner for import funds to X-Chain and P-Chain +// recipientOwner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// recipientKey.Address(), +// }, +// } +// // Use the same outputs for both X-Chain and P-Chain exports +// exportOutputs := []*secp256k1fx.TransferOutput{ +// { +// Amt: txAmount, +// OutputOwners: secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// keychain.Keys[0].Address(), +// }, +// }, +// }, +// } + +// ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { +// _, err := cWallet.IssueExportTx( +// xWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { +// _, err := xWallet.IssueImportTx( +// cWallet.BlockchainID(), +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { +// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { +// _, err := cWallet.IssueExportTx( +// constants.PlatformChainID, +// exportOutputs, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { +// _, err = pWallet.IssueImportTx( +// cWallet.BlockchainID(), +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { +// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) +// }) +// }) diff --git a/tests/e2e/e2e.go b/tests/e2e/e2e.go index 130f33f1197c..c124d50adb3b 100644 --- a/tests/e2e/e2e.go +++ b/tests/e2e/e2e.go @@ -7,22 +7,24 @@ package e2e import ( "context" "encoding/json" - "errors" - "fmt" - "math/big" + + // "errors" + // "fmt" + // "math/big" "math/rand" "os" "path/filepath" - "strings" + + // "strings" "time" ginkgo "github.com/onsi/ginkgo/v2" "github.com/stretchr/testify/require" - "github.com/ava-labs/coreth/core/types" - "github.com/ava-labs/coreth/ethclient" - "github.com/ava-labs/coreth/interfaces" + // "github.com/ava-labs/coreth/core/types" + // "github.com/ava-labs/coreth/ethclient" + // "github.com/ava-labs/coreth/interfaces" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/tests" @@ -134,7 +136,7 @@ func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain, nodeURI tes baseWallet, err := primary.MakeWallet(DefaultContext(), &primary.WalletConfig{ URI: nodeURI.URI, AVAXKeychain: keychain, - EthKeychain: keychain, + // EthKeychain: keychain, }) te.require.NoError(err) return primary.NewWalletWithOptions( @@ -147,16 +149,16 @@ func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain, nodeURI tes ) } -// Create a new eth client targeting the specified node URI. -// TODO(marun) Make this a regular function. -func (te *TestEnvironment) NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { - tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) - nodeAddress := strings.Split(nodeURI.URI, "//")[1] - uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) - client, err := ethclient.Dial(uri) - te.require.NoError(err) - return client -} +// // Create a new eth client targeting the specified node URI. +// // TODO(marun) Make this a regular function. +// func (te *TestEnvironment) NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { +// tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) +// nodeAddress := strings.Split(nodeURI.URI, "//")[1] +// uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) +// client, err := ethclient.Dial(uri) +// te.require.NoError(err) +// return client +// } // Create a new private network that is not shared with other tests. func (te *TestEnvironment) NewPrivateNetwork() testnet.Network { @@ -231,49 +233,49 @@ func WaitForHealthy(node testnet.Node) { require.NoError(ginkgo.GinkgoT(), testnet.WaitForHealthy(DefaultContext(), node)) } -// Sends an eth transaction, waits for the transaction receipt to be issued -// and checks that the receipt indicates success. -func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { - require := require.New(ginkgo.GinkgoT()) - - txID := signedTx.Hash() - tests.Outf(" sending eth transaction with ID: %s\n", txID) - - require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) - - // Wait for the receipt - var receipt *types.Receipt - Eventually(func() bool { - var err error - receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) - if errors.Is(err, interfaces.NotFound) { - return false // Transaction is still pending - } - require.NoError(err) - return true - }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") - - require.Equal(receipt.Status, types.ReceiptStatusSuccessful) - return receipt -} - -// Determines the suggested gas price for the configured client that will -// maximize the chances of transaction acceptance. -func SuggestGasPrice(ethClient ethclient.Client) *big.Int { - gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) - require.NoError(ginkgo.GinkgoT(), err) - // Double the suggested gas price to maximize the chances of - // acceptance. Maybe this can be revisited pending resolution of - // https://github.com/ava-labs/coreth/issues/314. - gasPrice.Add(gasPrice, gasPrice) - return gasPrice -} - -// Helper simplifying use via an option of a gas price appropriate for testing. -func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { - baseFee := SuggestGasPrice(ethClient) - return common.WithBaseFee(baseFee) -} +// // Sends an eth transaction, waits for the transaction receipt to be issued +// // and checks that the receipt indicates success. +// func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { +// require := require.New(ginkgo.GinkgoT()) + +// txID := signedTx.Hash() +// tests.Outf(" sending eth transaction with ID: %s\n", txID) + +// require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) + +// // Wait for the receipt +// var receipt *types.Receipt +// Eventually(func() bool { +// var err error +// receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) +// if errors.Is(err, interfaces.NotFound) { +// return false // Transaction is still pending +// } +// require.NoError(err) +// return true +// }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") + +// require.Equal(receipt.Status, types.ReceiptStatusSuccessful) +// return receipt +// } + +// // Determines the suggested gas price for the configured client that will +// // maximize the chances of transaction acceptance. +// func SuggestGasPrice(ethClient ethclient.Client) *big.Int { +// gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) +// require.NoError(ginkgo.GinkgoT(), err) +// // Double the suggested gas price to maximize the chances of +// // acceptance. Maybe this can be revisited pending resolution of +// // https://github.com/ava-labs/coreth/issues/314. +// gasPrice.Add(gasPrice, gasPrice) +// return gasPrice +// } + +// // Helper simplifying use via an option of a gas price appropriate for testing. +// func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { +// baseFee := SuggestGasPrice(ethClient) +// return common.WithBaseFee(baseFee) +// } // Verify that a new node can bootstrap into the network. func CheckBootstrapIsPossible(network testnet.Network) { diff --git a/tests/e2e/p/interchain_workflow.go b/tests/e2e/p/interchain_workflow.go index 10c15fd002a7..c5bc47517967 100644 --- a/tests/e2e/p/interchain_workflow.go +++ b/tests/e2e/p/interchain_workflow.go @@ -3,226 +3,226 @@ package p -import ( - "math/big" - "time" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/spf13/cast" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/api/info" - "github.com/ava-labs/avalanchego/config" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/tests/fixture/testnet" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/platformvm/reward" - "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { - require := require.New(ginkgo.GinkgoT()) - - const ( - transferAmount = 10 * units.Avax - weight = 2_000 * units.Avax // Used for both validation and delegation - ) - - ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { - network := e2e.Env.GetNetwork() - - ginkgo.By("checking that the network has a compatible minimum stake duration", func() { - minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) - require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) - }) - - ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") - factory := secp256k1.Factory{} - recipientKey, err := factory.NewPrivateKey() - require.NoError(err) - keychain := e2e.Env.NewKeychain(1) - keychain.Add(recipientKey) - nodeURI := e2e.Env.GetRandomNodeURI() - baseWallet := e2e.Env.NewWallet(keychain, nodeURI) - xWallet := baseWallet.X() - cWallet := baseWallet.C() - pWallet := baseWallet.P() - - ginkgo.By("defining common configuration") - recipientEthAddress := evm.GetEthAddress(recipientKey) - avaxAssetID := xWallet.AVAXAssetID() - // Use the same owner for sending to X-Chain and importing funds to P-Chain - recipientOwner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - recipientKey.Address(), - }, - } - // Use the same outputs for both X-Chain and C-Chain exports - exportOutputs := []*avax.TransferableOutput{ - { - Asset: avax.Asset{ - ID: avaxAssetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: transferAmount, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - keychain.Keys[0].Address(), - }, - }, - }, - }, - } - - ginkgo.By("adding new node and waiting for it to report healthy") - node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) - e2e.WaitForHealthy(node) - - ginkgo.By("retrieving new node's id and pop") - infoClient := info.NewClient(node.GetProcessContext().URI) - nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) - require.NoError(err) - - ginkgo.By("adding the new node as a validator", func() { - startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) - // Validation duration doesn't actually matter to this - // test - it is only ensuring that adding a validator - // doesn't break interchain transfer. - endTime := startTime.Add(30 * time.Second) - - rewardKey, err := factory.NewPrivateKey() - require.NoError(err) - - const ( - delegationPercent = 0.10 // 10% - delegationShare = reward.PercentDenominator * delegationPercent - ) - - _, err = pWallet.IssueAddPermissionlessValidatorTx( - &txs.SubnetValidator{ - Validator: txs.Validator{ - NodeID: nodeID, - Start: uint64(startTime.Unix()), - End: uint64(endTime.Unix()), - Wght: weight, - }, - Subnet: constants.PrimaryNetworkID, - }, - nodePOP, - pWallet.AVAXAssetID(), - &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{rewardKey.Address()}, - }, - &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{rewardKey.Address()}, - }, - delegationShare, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("adding a delegator to the new node", func() { - startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) - // Delegation duration doesn't actually matter to this - // test - it is only ensuring that adding a delegator - // doesn't break interchain transfer. - endTime := startTime.Add(15 * time.Second) - - rewardKey, err := factory.NewPrivateKey() - require.NoError(err) - - _, err = pWallet.IssueAddPermissionlessDelegatorTx( - &txs.SubnetValidator{ - Validator: txs.Validator{ - NodeID: nodeID, - Start: uint64(startTime.Unix()), - End: uint64(endTime.Unix()), - Wght: weight, - }, - Subnet: constants.PrimaryNetworkID, - }, - pWallet.AVAXAssetID(), - &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{rewardKey.Address()}, - }, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { - _, err := pWallet.IssueExportTx( - xWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { - _, err := xWallet.IssueImportTx( - constants.PlatformChainID, - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { - balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { - _, err := pWallet.IssueExportTx( - cWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("initializing a new eth client") - ethClient := e2e.Env.NewEthClient(nodeURI) - - ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { - _, err := cWallet.IssueImportTx( - constants.PlatformChainID, - recipientEthAddress, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") - balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) - require.NoError(err) - require.Positive(balance.Cmp(big.NewInt(0))) - - ginkgo.By("stopping validator node to free up resources for a bootstrap check") - require.NoError(node.Stop()) - - e2e.CheckBootstrapIsPossible(network) - }) -}) +// import ( +// "math/big" +// "time" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/spf13/cast" + +// "github.com/stretchr/testify/require" + +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/api/info" +// "github.com/ava-labs/avalanchego/config" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/tests/fixture/testnet" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/platformvm/reward" +// "github.com/ava-labs/avalanchego/vms/platformvm/txs" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { +// require := require.New(ginkgo.GinkgoT()) + +// const ( +// transferAmount = 10 * units.Avax +// weight = 2_000 * units.Avax // Used for both validation and delegation +// ) + +// ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { +// network := e2e.Env.GetNetwork() + +// ginkgo.By("checking that the network has a compatible minimum stake duration", func() { +// minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) +// require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) +// }) + +// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") +// factory := secp256k1.Factory{} +// recipientKey, err := factory.NewPrivateKey() +// require.NoError(err) +// keychain := e2e.Env.NewKeychain(1) +// keychain.Add(recipientKey) +// nodeURI := e2e.Env.GetRandomNodeURI() +// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) +// xWallet := baseWallet.X() +// cWallet := baseWallet.C() +// pWallet := baseWallet.P() + +// ginkgo.By("defining common configuration") +// recipientEthAddress := evm.GetEthAddress(recipientKey) +// avaxAssetID := xWallet.AVAXAssetID() +// // Use the same owner for sending to X-Chain and importing funds to P-Chain +// recipientOwner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// recipientKey.Address(), +// }, +// } +// // Use the same outputs for both X-Chain and C-Chain exports +// exportOutputs := []*avax.TransferableOutput{ +// { +// Asset: avax.Asset{ +// ID: avaxAssetID, +// }, +// Out: &secp256k1fx.TransferOutput{ +// Amt: transferAmount, +// OutputOwners: secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// keychain.Keys[0].Address(), +// }, +// }, +// }, +// }, +// } + +// ginkgo.By("adding new node and waiting for it to report healthy") +// node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) +// e2e.WaitForHealthy(node) + +// ginkgo.By("retrieving new node's id and pop") +// infoClient := info.NewClient(node.GetProcessContext().URI) +// nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) +// require.NoError(err) + +// ginkgo.By("adding the new node as a validator", func() { +// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) +// // Validation duration doesn't actually matter to this +// // test - it is only ensuring that adding a validator +// // doesn't break interchain transfer. +// endTime := startTime.Add(30 * time.Second) + +// rewardKey, err := factory.NewPrivateKey() +// require.NoError(err) + +// const ( +// delegationPercent = 0.10 // 10% +// delegationShare = reward.PercentDenominator * delegationPercent +// ) + +// _, err = pWallet.IssueAddPermissionlessValidatorTx( +// &txs.SubnetValidator{ +// Validator: txs.Validator{ +// NodeID: nodeID, +// Start: uint64(startTime.Unix()), +// End: uint64(endTime.Unix()), +// Wght: weight, +// }, +// Subnet: constants.PrimaryNetworkID, +// }, +// nodePOP, +// pWallet.AVAXAssetID(), +// &secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{rewardKey.Address()}, +// }, +// &secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{rewardKey.Address()}, +// }, +// delegationShare, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("adding a delegator to the new node", func() { +// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) +// // Delegation duration doesn't actually matter to this +// // test - it is only ensuring that adding a delegator +// // doesn't break interchain transfer. +// endTime := startTime.Add(15 * time.Second) + +// rewardKey, err := factory.NewPrivateKey() +// require.NoError(err) + +// _, err = pWallet.IssueAddPermissionlessDelegatorTx( +// &txs.SubnetValidator{ +// Validator: txs.Validator{ +// NodeID: nodeID, +// Start: uint64(startTime.Unix()), +// End: uint64(endTime.Unix()), +// Wght: weight, +// }, +// Subnet: constants.PrimaryNetworkID, +// }, +// pWallet.AVAXAssetID(), +// &secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{rewardKey.Address()}, +// }, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { +// _, err := pWallet.IssueExportTx( +// xWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { +// _, err := xWallet.IssueImportTx( +// constants.PlatformChainID, +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { +// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { +// _, err := pWallet.IssueExportTx( +// cWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("initializing a new eth client") +// ethClient := e2e.Env.NewEthClient(nodeURI) + +// ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { +// _, err := cWallet.IssueImportTx( +// constants.PlatformChainID, +// recipientEthAddress, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") +// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) +// require.NoError(err) +// require.Positive(balance.Cmp(big.NewInt(0))) + +// ginkgo.By("stopping validator node to free up resources for a bootstrap check") +// require.NoError(node.Stop()) + +// e2e.CheckBootstrapIsPossible(network) +// }) +// }) diff --git a/tests/e2e/x/interchain_workflow.go b/tests/e2e/x/interchain_workflow.go index 550689ff60c9..5443e1a54ad4 100644 --- a/tests/e2e/x/interchain_workflow.go +++ b/tests/e2e/x/interchain_workflow.go @@ -3,152 +3,152 @@ package x -import ( - "math/big" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { - require := require.New(ginkgo.GinkgoT()) - - const transferAmount = 10 * units.Avax - - ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { - nodeURI := e2e.Env.GetRandomNodeURI() - - ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") - factory := secp256k1.Factory{} - recipientKey, err := factory.NewPrivateKey() - require.NoError(err) - keychain := e2e.Env.NewKeychain(1) - keychain.Add(recipientKey) - baseWallet := e2e.Env.NewWallet(keychain, nodeURI) - xWallet := baseWallet.X() - cWallet := baseWallet.C() - pWallet := baseWallet.P() - - ginkgo.By("defining common configuration") - recipientEthAddress := evm.GetEthAddress(recipientKey) - avaxAssetID := xWallet.AVAXAssetID() - // Use the same owner for sending to X-Chain and importing funds to P-Chain - recipientOwner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - recipientKey.Address(), - }, - } - // Use the same outputs for both C-Chain and P-Chain exports - exportOutputs := []*avax.TransferableOutput{ - { - Asset: avax.Asset{ - ID: avaxAssetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: transferAmount, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - keychain.Keys[0].Address(), - }, - }, - }, - }, - } - - ginkgo.By("sending funds from one address to another on the X-Chain", func() { - _, err = xWallet.IssueBaseTx( - []*avax.TransferableOutput{{ - Asset: avax.Asset{ - ID: avaxAssetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: transferAmount, - OutputOwners: recipientOwner, - }, - }}, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { - balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { - _, err := xWallet.IssueExportTx( - cWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("initializing a new eth client") - ethClient := e2e.Env.NewEthClient(nodeURI) - - ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { - _, err := cWallet.IssueImportTx( - xWallet.BlockchainID(), - recipientEthAddress, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") - e2e.Eventually(func() bool { - balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) - require.NoError(err) - return balance.Cmp(big.NewInt(0)) > 0 - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") - - ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { - _, err := xWallet.IssueExportTx( - constants.PlatformChainID, - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { - _, err := pWallet.IssueImportTx( - xWallet.BlockchainID(), - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { - balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) - }) -}) +// import ( +// "math/big" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/stretchr/testify/require" + +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { +// require := require.New(ginkgo.GinkgoT()) + +// const transferAmount = 10 * units.Avax + +// ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { +// nodeURI := e2e.Env.GetRandomNodeURI() + +// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") +// factory := secp256k1.Factory{} +// recipientKey, err := factory.NewPrivateKey() +// require.NoError(err) +// keychain := e2e.Env.NewKeychain(1) +// keychain.Add(recipientKey) +// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) +// xWallet := baseWallet.X() +// cWallet := baseWallet.C() +// pWallet := baseWallet.P() + +// ginkgo.By("defining common configuration") +// recipientEthAddress := evm.GetEthAddress(recipientKey) +// avaxAssetID := xWallet.AVAXAssetID() +// // Use the same owner for sending to X-Chain and importing funds to P-Chain +// recipientOwner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// recipientKey.Address(), +// }, +// } +// // Use the same outputs for both C-Chain and P-Chain exports +// exportOutputs := []*avax.TransferableOutput{ +// { +// Asset: avax.Asset{ +// ID: avaxAssetID, +// }, +// Out: &secp256k1fx.TransferOutput{ +// Amt: transferAmount, +// OutputOwners: secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// keychain.Keys[0].Address(), +// }, +// }, +// }, +// }, +// } + +// ginkgo.By("sending funds from one address to another on the X-Chain", func() { +// _, err = xWallet.IssueBaseTx( +// []*avax.TransferableOutput{{ +// Asset: avax.Asset{ +// ID: avaxAssetID, +// }, +// Out: &secp256k1fx.TransferOutput{ +// Amt: transferAmount, +// OutputOwners: recipientOwner, +// }, +// }}, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { +// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { +// _, err := xWallet.IssueExportTx( +// cWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("initializing a new eth client") +// ethClient := e2e.Env.NewEthClient(nodeURI) + +// ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { +// _, err := cWallet.IssueImportTx( +// xWallet.BlockchainID(), +// recipientEthAddress, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") +// e2e.Eventually(func() bool { +// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) +// require.NoError(err) +// return balance.Cmp(big.NewInt(0)) > 0 +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") + +// ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { +// _, err := xWallet.IssueExportTx( +// constants.PlatformChainID, +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { +// _, err := pWallet.IssueImportTx( +// xWallet.BlockchainID(), +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { +// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) +// }) +// }) diff --git a/tests/fixture/testnet/config.go b/tests/fixture/testnet/config.go index 10d51104eef4..80a795b3d5e2 100644 --- a/tests/fixture/testnet/config.go +++ b/tests/fixture/testnet/config.go @@ -15,9 +15,9 @@ import ( "github.com/spf13/cast" - "github.com/ava-labs/coreth/core" - "github.com/ava-labs/coreth/params" - "github.com/ava-labs/coreth/plugin/evm" + // "github.com/ava-labs/coreth/core" + // "github.com/ava-labs/coreth/params" + // "github.com/ava-labs/coreth/plugin/evm" "github.com/ava-labs/avalanchego/config" "github.com/ava-labs/avalanchego/genesis" @@ -143,15 +143,15 @@ func (c *NetworkConfig) EnsureGenesis(networkID uint32, validatorIDs []ids.NodeI // Ensure pre-funded keys have arbitrary large balances on both chains to support testing xChainBalances := make(XChainBalanceMap, len(c.FundedKeys)) - cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) - for _, key := range c.FundedKeys { - xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount - cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ - Balance: DefaultFundedKeyCChainAmount, - } - } - - genesis, err := NewTestGenesis(networkID, xChainBalances, cChainBalances, validatorIDs) + // cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) + // for _, key := range c.FundedKeys { + // xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount + // cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ + // Balance: DefaultFundedKeyCChainAmount, + // } + // } + + genesis, err := NewTestGenesis(networkID, xChainBalances /*cChainBalances,*/, validatorIDs) if err != nil { return err } @@ -311,7 +311,7 @@ type XChainBalanceMap map[ids.ShortID]uint64 func NewTestGenesis( networkID uint32, xChainBalances XChainBalanceMap, - cChainBalances core.GenesisAlloc, + // cChainBalances core.GenesisAlloc, validatorIDs []ids.NodeID, ) (*genesis.UnparsedConfig, error) { // Validate inputs @@ -322,7 +322,7 @@ func NewTestGenesis( if len(validatorIDs) == 0 { return nil, errMissingValidatorsForGenesis } - if len(xChainBalances) == 0 || len(cChainBalances) == 0 { + if len(xChainBalances) == 0 /*|| len(cChainBalances) == 0*/ { return nil, errMissingBalancesForGenesis } @@ -394,20 +394,20 @@ func NewTestGenesis( ) } - // Define C-Chain genesis - cChainGenesis := &core.Genesis{ - Config: ¶ms.ChainConfig{ - ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary - }, - Difficulty: big.NewInt(0), // Difficulty is a mandatory field - GasLimit: DefaultGasLimit, - Alloc: cChainBalances, - } - cChainGenesisBytes, err := json.Marshal(cChainGenesis) - if err != nil { - return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) - } - config.CChainGenesis = string(cChainGenesisBytes) + // // Define C-Chain genesis + // cChainGenesis := &core.Genesis{ + // Config: ¶ms.ChainConfig{ + // ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary + // }, + // Difficulty: big.NewInt(0), // Difficulty is a mandatory field + // GasLimit: DefaultGasLimit, + // Alloc: cChainBalances, + // } + // cChainGenesisBytes, err := json.Marshal(cChainGenesis) + // if err != nil { + // return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) + // } + // config.CChainGenesis = string(cChainGenesisBytes) // Give staking rewards for initial validators to a random address. Any testing of staking rewards // will be easier to perform with nodes other than the initial validators since the timing of diff --git a/vms/example/xsvm/cmd/chain/create/cmd.go b/vms/example/xsvm/cmd/chain/create/cmd.go index 1f00491a4ce6..043b4298dcdf 100644 --- a/vms/example/xsvm/cmd/chain/create/cmd.go +++ b/vms/example/xsvm/cmd/chain/create/cmd.go @@ -42,9 +42,9 @@ func createFunc(c *cobra.Command, args []string) error { // that [uri] is hosting. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: config.URI, - AVAXKeychain: kc, - EthKeychain: kc, + URI: config.URI, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(config.SubnetID), }) if err != nil { diff --git a/wallet/chain/c/backend.go b/wallet/chain/c/backend.go index 0a735116b646..b88c8c643bc3 100644 --- a/wallet/chain/c/backend.go +++ b/wallet/chain/c/backend.go @@ -3,153 +3,153 @@ package c -import ( - "errors" - "fmt" - "math/big" - "sync" - - stdcontext "context" - - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/utils/math" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var ( - _ Backend = (*backend)(nil) - - errUnknownTxType = errors.New("unknown tx type") -) - -// Backend defines the full interface required to support a C-chain wallet. -type Backend interface { - common.ChainUTXOs - BuilderBackend - SignerBackend - - AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error -} - -type backend struct { - Context - common.ChainUTXOs - - accountsLock sync.RWMutex - accounts map[ethcommon.Address]*Account -} - -type Account struct { - Balance *big.Int - Nonce uint64 -} - -func NewBackend( - ctx Context, - utxos common.ChainUTXOs, - accounts map[ethcommon.Address]*Account, -) Backend { - return &backend{ - Context: ctx, - ChainUTXOs: utxos, - accounts: accounts, - } -} - -func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { - switch tx := tx.UnsignedAtomicTx.(type) { - case *evm.UnsignedImportTx: - for _, input := range tx.ImportedInputs { - utxoID := input.InputID() - if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { - return err - } - } - - b.accountsLock.Lock() - defer b.accountsLock.Unlock() - - for _, output := range tx.Outs { - account, ok := b.accounts[output.Address] - if !ok { - continue - } - - balance := new(big.Int).SetUint64(output.Amount) - balance.Mul(balance, avaxConversionRate) - account.Balance.Add(account.Balance, balance) - } - case *evm.UnsignedExportTx: - txID := tx.ID() - for i, out := range tx.ExportedOutputs { - err := b.AddUTXO( - ctx, - tx.DestinationChain, - &avax.UTXO{ - UTXOID: avax.UTXOID{ - TxID: txID, - OutputIndex: uint32(i), - }, - Asset: avax.Asset{ID: out.AssetID()}, - Out: out.Out, - }, - ) - if err != nil { - return err - } - } - - b.accountsLock.Lock() - defer b.accountsLock.Unlock() - - for _, input := range tx.Ins { - account, ok := b.accounts[input.Address] - if !ok { - continue - } - - balance := new(big.Int).SetUint64(input.Amount) - balance.Mul(balance, avaxConversionRate) - if account.Balance.Cmp(balance) == -1 { - return errInsufficientFunds - } - account.Balance.Sub(account.Balance, balance) - - newNonce, err := math.Add64(input.Nonce, 1) - if err != nil { - return err - } - account.Nonce = newNonce - } - default: - return fmt.Errorf("%w: %T", errUnknownTxType, tx) - } - return nil -} - -func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { - b.accountsLock.RLock() - defer b.accountsLock.RUnlock() - - account, exists := b.accounts[addr] - if !exists { - return nil, database.ErrNotFound - } - return account.Balance, nil -} - -func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { - b.accountsLock.RLock() - defer b.accountsLock.RUnlock() - - account, exists := b.accounts[addr] - if !exists { - return 0, database.ErrNotFound - } - return account.Nonce, nil -} +// import ( +// "errors" +// "fmt" +// "math/big" +// "sync" + +// stdcontext "context" + +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/database" +// "github.com/ava-labs/avalanchego/utils/math" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var ( +// _ Backend = (*backend)(nil) + +// errUnknownTxType = errors.New("unknown tx type") +// ) + +// // Backend defines the full interface required to support a C-chain wallet. +// type Backend interface { +// common.ChainUTXOs +// BuilderBackend +// SignerBackend + +// AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error +// } + +// type backend struct { +// Context +// common.ChainUTXOs + +// accountsLock sync.RWMutex +// accounts map[ethcommon.Address]*Account +// } + +// type Account struct { +// Balance *big.Int +// Nonce uint64 +// } + +// func NewBackend( +// ctx Context, +// utxos common.ChainUTXOs, +// accounts map[ethcommon.Address]*Account, +// ) Backend { +// return &backend{ +// Context: ctx, +// ChainUTXOs: utxos, +// accounts: accounts, +// } +// } + +// func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { +// switch tx := tx.UnsignedAtomicTx.(type) { +// case *evm.UnsignedImportTx: +// for _, input := range tx.ImportedInputs { +// utxoID := input.InputID() +// if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { +// return err +// } +// } + +// b.accountsLock.Lock() +// defer b.accountsLock.Unlock() + +// for _, output := range tx.Outs { +// account, ok := b.accounts[output.Address] +// if !ok { +// continue +// } + +// balance := new(big.Int).SetUint64(output.Amount) +// balance.Mul(balance, avaxConversionRate) +// account.Balance.Add(account.Balance, balance) +// } +// case *evm.UnsignedExportTx: +// txID := tx.ID() +// for i, out := range tx.ExportedOutputs { +// err := b.AddUTXO( +// ctx, +// tx.DestinationChain, +// &avax.UTXO{ +// UTXOID: avax.UTXOID{ +// TxID: txID, +// OutputIndex: uint32(i), +// }, +// Asset: avax.Asset{ID: out.AssetID()}, +// Out: out.Out, +// }, +// ) +// if err != nil { +// return err +// } +// } + +// b.accountsLock.Lock() +// defer b.accountsLock.Unlock() + +// for _, input := range tx.Ins { +// account, ok := b.accounts[input.Address] +// if !ok { +// continue +// } + +// balance := new(big.Int).SetUint64(input.Amount) +// balance.Mul(balance, avaxConversionRate) +// if account.Balance.Cmp(balance) == -1 { +// return errInsufficientFunds +// } +// account.Balance.Sub(account.Balance, balance) + +// newNonce, err := math.Add64(input.Nonce, 1) +// if err != nil { +// return err +// } +// account.Nonce = newNonce +// } +// default: +// return fmt.Errorf("%w: %T", errUnknownTxType, tx) +// } +// return nil +// } + +// func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { +// b.accountsLock.RLock() +// defer b.accountsLock.RUnlock() + +// account, exists := b.accounts[addr] +// if !exists { +// return nil, database.ErrNotFound +// } +// return account.Balance, nil +// } + +// func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { +// b.accountsLock.RLock() +// defer b.accountsLock.RUnlock() + +// account, exists := b.accounts[addr] +// if !exists { +// return 0, database.ErrNotFound +// } +// return account.Nonce, nil +// } diff --git a/wallet/chain/c/builder.go b/wallet/chain/c/builder.go index d2d088e88a53..c51d2647777e 100644 --- a/wallet/chain/c/builder.go +++ b/wallet/chain/c/builder.go @@ -3,399 +3,399 @@ package c -import ( - "errors" - "math/big" - - stdcontext "context" - - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils" - "github.com/ava-labs/avalanchego/utils/math" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -const avaxConversionRateInt = 1_000_000_000 - -var ( - _ Builder = (*builder)(nil) - - errInsufficientFunds = errors.New("insufficient funds") - - // avaxConversionRate is the conversion rate between the smallest - // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest - // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. - // - // This is only required for AVAX because the denomination of 1 AVAX is 9 - // decimal places on the X and P chains, but is 18 decimal places within the - // EVM. - avaxConversionRate = big.NewInt(avaxConversionRateInt) -) - -// Builder provides a convenient interface for building unsigned C-chain -// transactions. -type Builder interface { - // GetBalance calculates the amount of AVAX that this builder has control - // over. - GetBalance( - options ...common.Option, - ) (*big.Int, error) - - // GetImportableBalance calculates the amount of AVAX that this builder - // could import from the provided chain. - // - // - [chainID] specifies the chain the funds are from. - GetImportableBalance( - chainID ids.ID, - options ...common.Option, - ) (uint64, error) - - // NewImportTx creates an import transaction that attempts to consume all - // the available UTXOs and import the funds to [to]. - // - // - [chainID] specifies the chain to be importing funds from. - // - [to] specifies where to send the imported funds to. - // - [baseFee] specifies the fee price willing to be paid by this tx. - NewImportTx( - chainID ids.ID, - to ethcommon.Address, - baseFee *big.Int, - options ...common.Option, - ) (*evm.UnsignedImportTx, error) - - // NewExportTx creates an export transaction that attempts to send all the - // provided [outputs] to the requested [chainID]. - // - // - [chainID] specifies the chain to be exporting the funds to. - // - [outputs] specifies the outputs to send to the [chainID]. - // - [baseFee] specifies the fee price willing to be paid by this tx. - NewExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - baseFee *big.Int, - options ...common.Option, - ) (*evm.UnsignedExportTx, error) -} - -// BuilderBackend specifies the required information needed to build unsigned -// C-chain transactions. -type BuilderBackend interface { - Context - - UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) - Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) - Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) -} - -type builder struct { - avaxAddrs set.Set[ids.ShortID] - ethAddrs set.Set[ethcommon.Address] - backend BuilderBackend -} - -// NewBuilder returns a new transaction builder. -// -// - [avaxAddrs] is the set of addresses in the AVAX format that the builder -// assumes can be used when signing the transactions in the future. -// - [ethAddrs] is the set of addresses in the Eth format that the builder -// assumes can be used when signing the transactions in the future. -// - [backend] provides the required access to the chain's context and state -// to build out the transactions. -func NewBuilder( - avaxAddrs set.Set[ids.ShortID], - ethAddrs set.Set[ethcommon.Address], - backend BuilderBackend, -) Builder { - return &builder{ - avaxAddrs: avaxAddrs, - ethAddrs: ethAddrs, - backend: backend, - } -} - -func (b *builder) GetBalance( - options ...common.Option, -) (*big.Int, error) { - var ( - ops = common.NewOptions(options) - ctx = ops.Context() - addrs = ops.EthAddresses(b.ethAddrs) - totalBalance = new(big.Int) - ) - for addr := range addrs { - balance, err := b.backend.Balance(ctx, addr) - if err != nil { - return nil, err - } - totalBalance.Add(totalBalance, balance) - } - - return totalBalance, nil -} - -func (b *builder) GetImportableBalance( - chainID ids.ID, - options ...common.Option, -) (uint64, error) { - ops := common.NewOptions(options) - utxos, err := b.backend.UTXOs(ops.Context(), chainID) - if err != nil { - return 0, err - } - - var ( - addrs = ops.Addresses(b.avaxAddrs) - minIssuanceTime = ops.MinIssuanceTime() - avaxAssetID = b.backend.AVAXAssetID() - balance uint64 - ) - for _, utxo := range utxos { - amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) - if !ok { - continue - } - - newBalance, err := math.Add64(balance, amount) - if err != nil { - return 0, err - } - balance = newBalance - } - - return balance, nil -} - -func (b *builder) NewImportTx( - chainID ids.ID, - to ethcommon.Address, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedImportTx, error) { - ops := common.NewOptions(options) - utxos, err := b.backend.UTXOs(ops.Context(), chainID) - if err != nil { - return nil, err - } - - var ( - addrs = ops.Addresses(b.avaxAddrs) - minIssuanceTime = ops.MinIssuanceTime() - avaxAssetID = b.backend.AVAXAssetID() - - importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) - importedAmount uint64 - ) - for _, utxo := range utxos { - amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) - if !ok { - continue - } - - importedInputs = append(importedInputs, &avax.TransferableInput{ - UTXOID: utxo.UTXOID, - Asset: utxo.Asset, - In: &secp256k1fx.TransferInput{ - Amt: amount, - Input: secp256k1fx.Input{ - SigIndices: inputSigIndices, - }, - }, - }) - - newImportedAmount, err := math.Add64(importedAmount, amount) - if err != nil { - return nil, err - } - importedAmount = newImportedAmount - } - - utils.Sort(importedInputs) - tx := &evm.UnsignedImportTx{ - NetworkID: b.backend.NetworkID(), - BlockchainID: b.backend.BlockchainID(), - SourceChain: chainID, - ImportedInputs: importedInputs, - } - - // We must initialize the bytes of the tx to calculate the initial cost - wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} - if err := wrappedTx.Sign(evm.Codec, nil); err != nil { - return nil, err - } - - gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) - if err != nil { - return nil, err - } - gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas - - txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) - if err != nil { - return nil, err - } - - if importedAmount <= txFee { - return nil, errInsufficientFunds - } - - tx.Outs = []evm.EVMOutput{{ - Address: to, - Amount: importedAmount - txFee, - AssetID: avaxAssetID, - }} - return tx, nil -} - -func (b *builder) NewExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedExportTx, error) { - var ( - avaxAssetID = b.backend.AVAXAssetID() - exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) - exportedAmount uint64 - ) - for i, output := range outputs { - exportedOutputs[i] = &avax.TransferableOutput{ - Asset: avax.Asset{ID: avaxAssetID}, - Out: output, - } - - newExportedAmount, err := math.Add64(exportedAmount, output.Amt) - if err != nil { - return nil, err - } - exportedAmount = newExportedAmount - } - - avax.SortTransferableOutputs(exportedOutputs, evm.Codec) - tx := &evm.UnsignedExportTx{ - NetworkID: b.backend.NetworkID(), - BlockchainID: b.backend.BlockchainID(), - DestinationChain: chainID, - ExportedOutputs: exportedOutputs, - } - - // We must initialize the bytes of the tx to calculate the initial cost - wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} - if err := wrappedTx.Sign(evm.Codec, nil); err != nil { - return nil, err - } - - cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) - if err != nil { - return nil, err - } - - initialFee, err := evm.CalculateDynamicFee(cost, baseFee) - if err != nil { - return nil, err - } - - amountToConsume, err := math.Add64(exportedAmount, initialFee) - if err != nil { - return nil, err - } - - var ( - ops = common.NewOptions(options) - ctx = ops.Context() - addrs = ops.EthAddresses(b.ethAddrs) - inputs = make([]evm.EVMInput, 0, addrs.Len()) - ) - for addr := range addrs { - if amountToConsume == 0 { - break - } - - prevFee, err := evm.CalculateDynamicFee(cost, baseFee) - if err != nil { - return nil, err - } - - newCost := cost + evm.EVMInputGas - newFee, err := evm.CalculateDynamicFee(newCost, baseFee) - if err != nil { - return nil, err - } - - additionalFee := newFee - prevFee - - balance, err := b.backend.Balance(ctx, addr) - if err != nil { - return nil, err - } - - // Since the asset is AVAX, we divide by the avaxConversionRate to - // convert back to the correct denomination of AVAX that can be - // exported. - avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() - - // If the balance for [addr] is insufficient to cover the additional - // cost of adding an input to the transaction, skip adding the input - // altogether. - if avaxBalance <= additionalFee { - continue - } - - // Update the cost for the next iteration - cost = newCost - - amountToConsume, err = math.Add64(amountToConsume, additionalFee) - if err != nil { - return nil, err - } - - nonce, err := b.backend.Nonce(ctx, addr) - if err != nil { - return nil, err - } - - inputAmount := math.Min(amountToConsume, avaxBalance) - inputs = append(inputs, evm.EVMInput{ - Address: addr, - Amount: inputAmount, - AssetID: avaxAssetID, - Nonce: nonce, - }) - amountToConsume -= inputAmount - } - - if amountToConsume > 0 { - return nil, errInsufficientFunds - } - - utils.Sort(inputs) - tx.Ins = inputs - return tx, nil -} - -func getSpendableAmount( - utxo *avax.UTXO, - addrs set.Set[ids.ShortID], - minIssuanceTime uint64, - avaxAssetID ids.ID, -) (uint64, []uint32, bool) { - if utxo.Asset.ID != avaxAssetID { - // Only AVAX can be imported - return 0, nil, false - } - - out, ok := utxo.Out.(*secp256k1fx.TransferOutput) - if !ok { - // Can't import an unknown transfer output type - return 0, nil, false - } - - inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) - return out.Amt, inputSigIndices, ok -} +// import ( +// "errors" +// "math/big" + +// stdcontext "context" + +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils" +// "github.com/ava-labs/avalanchego/utils/math" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// const avaxConversionRateInt = 1_000_000_000 + +// var ( +// _ Builder = (*builder)(nil) + +// errInsufficientFunds = errors.New("insufficient funds") + +// // avaxConversionRate is the conversion rate between the smallest +// // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest +// // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. +// // +// // This is only required for AVAX because the denomination of 1 AVAX is 9 +// // decimal places on the X and P chains, but is 18 decimal places within the +// // EVM. +// avaxConversionRate = big.NewInt(avaxConversionRateInt) +// ) + +// // Builder provides a convenient interface for building unsigned C-chain +// // transactions. +// type Builder interface { +// // GetBalance calculates the amount of AVAX that this builder has control +// // over. +// GetBalance( +// options ...common.Option, +// ) (*big.Int, error) + +// // GetImportableBalance calculates the amount of AVAX that this builder +// // could import from the provided chain. +// // +// // - [chainID] specifies the chain the funds are from. +// GetImportableBalance( +// chainID ids.ID, +// options ...common.Option, +// ) (uint64, error) + +// // NewImportTx creates an import transaction that attempts to consume all +// // the available UTXOs and import the funds to [to]. +// // +// // - [chainID] specifies the chain to be importing funds from. +// // - [to] specifies where to send the imported funds to. +// // - [baseFee] specifies the fee price willing to be paid by this tx. +// NewImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedImportTx, error) + +// // NewExportTx creates an export transaction that attempts to send all the +// // provided [outputs] to the requested [chainID]. +// // +// // - [chainID] specifies the chain to be exporting the funds to. +// // - [outputs] specifies the outputs to send to the [chainID]. +// // - [baseFee] specifies the fee price willing to be paid by this tx. +// NewExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedExportTx, error) +// } + +// // BuilderBackend specifies the required information needed to build unsigned +// // C-chain transactions. +// type BuilderBackend interface { +// Context + +// UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) +// Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) +// Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) +// } + +// type builder struct { +// avaxAddrs set.Set[ids.ShortID] +// ethAddrs set.Set[ethcommon.Address] +// backend BuilderBackend +// } + +// // NewBuilder returns a new transaction builder. +// // +// // - [avaxAddrs] is the set of addresses in the AVAX format that the builder +// // assumes can be used when signing the transactions in the future. +// // - [ethAddrs] is the set of addresses in the Eth format that the builder +// // assumes can be used when signing the transactions in the future. +// // - [backend] provides the required access to the chain's context and state +// // to build out the transactions. +// func NewBuilder( +// avaxAddrs set.Set[ids.ShortID], +// ethAddrs set.Set[ethcommon.Address], +// backend BuilderBackend, +// ) Builder { +// return &builder{ +// avaxAddrs: avaxAddrs, +// ethAddrs: ethAddrs, +// backend: backend, +// } +// } + +// func (b *builder) GetBalance( +// options ...common.Option, +// ) (*big.Int, error) { +// var ( +// ops = common.NewOptions(options) +// ctx = ops.Context() +// addrs = ops.EthAddresses(b.ethAddrs) +// totalBalance = new(big.Int) +// ) +// for addr := range addrs { +// balance, err := b.backend.Balance(ctx, addr) +// if err != nil { +// return nil, err +// } +// totalBalance.Add(totalBalance, balance) +// } + +// return totalBalance, nil +// } + +// func (b *builder) GetImportableBalance( +// chainID ids.ID, +// options ...common.Option, +// ) (uint64, error) { +// ops := common.NewOptions(options) +// utxos, err := b.backend.UTXOs(ops.Context(), chainID) +// if err != nil { +// return 0, err +// } + +// var ( +// addrs = ops.Addresses(b.avaxAddrs) +// minIssuanceTime = ops.MinIssuanceTime() +// avaxAssetID = b.backend.AVAXAssetID() +// balance uint64 +// ) +// for _, utxo := range utxos { +// amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) +// if !ok { +// continue +// } + +// newBalance, err := math.Add64(balance, amount) +// if err != nil { +// return 0, err +// } +// balance = newBalance +// } + +// return balance, nil +// } + +// func (b *builder) NewImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedImportTx, error) { +// ops := common.NewOptions(options) +// utxos, err := b.backend.UTXOs(ops.Context(), chainID) +// if err != nil { +// return nil, err +// } + +// var ( +// addrs = ops.Addresses(b.avaxAddrs) +// minIssuanceTime = ops.MinIssuanceTime() +// avaxAssetID = b.backend.AVAXAssetID() + +// importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) +// importedAmount uint64 +// ) +// for _, utxo := range utxos { +// amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) +// if !ok { +// continue +// } + +// importedInputs = append(importedInputs, &avax.TransferableInput{ +// UTXOID: utxo.UTXOID, +// Asset: utxo.Asset, +// In: &secp256k1fx.TransferInput{ +// Amt: amount, +// Input: secp256k1fx.Input{ +// SigIndices: inputSigIndices, +// }, +// }, +// }) + +// newImportedAmount, err := math.Add64(importedAmount, amount) +// if err != nil { +// return nil, err +// } +// importedAmount = newImportedAmount +// } + +// utils.Sort(importedInputs) +// tx := &evm.UnsignedImportTx{ +// NetworkID: b.backend.NetworkID(), +// BlockchainID: b.backend.BlockchainID(), +// SourceChain: chainID, +// ImportedInputs: importedInputs, +// } + +// // We must initialize the bytes of the tx to calculate the initial cost +// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} +// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { +// return nil, err +// } + +// gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) +// if err != nil { +// return nil, err +// } +// gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas + +// txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) +// if err != nil { +// return nil, err +// } + +// if importedAmount <= txFee { +// return nil, errInsufficientFunds +// } + +// tx.Outs = []evm.EVMOutput{{ +// Address: to, +// Amount: importedAmount - txFee, +// AssetID: avaxAssetID, +// }} +// return tx, nil +// } + +// func (b *builder) NewExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedExportTx, error) { +// var ( +// avaxAssetID = b.backend.AVAXAssetID() +// exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) +// exportedAmount uint64 +// ) +// for i, output := range outputs { +// exportedOutputs[i] = &avax.TransferableOutput{ +// Asset: avax.Asset{ID: avaxAssetID}, +// Out: output, +// } + +// newExportedAmount, err := math.Add64(exportedAmount, output.Amt) +// if err != nil { +// return nil, err +// } +// exportedAmount = newExportedAmount +// } + +// avax.SortTransferableOutputs(exportedOutputs, evm.Codec) +// tx := &evm.UnsignedExportTx{ +// NetworkID: b.backend.NetworkID(), +// BlockchainID: b.backend.BlockchainID(), +// DestinationChain: chainID, +// ExportedOutputs: exportedOutputs, +// } + +// // We must initialize the bytes of the tx to calculate the initial cost +// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} +// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { +// return nil, err +// } + +// cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) +// if err != nil { +// return nil, err +// } + +// initialFee, err := evm.CalculateDynamicFee(cost, baseFee) +// if err != nil { +// return nil, err +// } + +// amountToConsume, err := math.Add64(exportedAmount, initialFee) +// if err != nil { +// return nil, err +// } + +// var ( +// ops = common.NewOptions(options) +// ctx = ops.Context() +// addrs = ops.EthAddresses(b.ethAddrs) +// inputs = make([]evm.EVMInput, 0, addrs.Len()) +// ) +// for addr := range addrs { +// if amountToConsume == 0 { +// break +// } + +// prevFee, err := evm.CalculateDynamicFee(cost, baseFee) +// if err != nil { +// return nil, err +// } + +// newCost := cost + evm.EVMInputGas +// newFee, err := evm.CalculateDynamicFee(newCost, baseFee) +// if err != nil { +// return nil, err +// } + +// additionalFee := newFee - prevFee + +// balance, err := b.backend.Balance(ctx, addr) +// if err != nil { +// return nil, err +// } + +// // Since the asset is AVAX, we divide by the avaxConversionRate to +// // convert back to the correct denomination of AVAX that can be +// // exported. +// avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() + +// // If the balance for [addr] is insufficient to cover the additional +// // cost of adding an input to the transaction, skip adding the input +// // altogether. +// if avaxBalance <= additionalFee { +// continue +// } + +// // Update the cost for the next iteration +// cost = newCost + +// amountToConsume, err = math.Add64(amountToConsume, additionalFee) +// if err != nil { +// return nil, err +// } + +// nonce, err := b.backend.Nonce(ctx, addr) +// if err != nil { +// return nil, err +// } + +// inputAmount := math.Min(amountToConsume, avaxBalance) +// inputs = append(inputs, evm.EVMInput{ +// Address: addr, +// Amount: inputAmount, +// AssetID: avaxAssetID, +// Nonce: nonce, +// }) +// amountToConsume -= inputAmount +// } + +// if amountToConsume > 0 { +// return nil, errInsufficientFunds +// } + +// utils.Sort(inputs) +// tx.Ins = inputs +// return tx, nil +// } + +// func getSpendableAmount( +// utxo *avax.UTXO, +// addrs set.Set[ids.ShortID], +// minIssuanceTime uint64, +// avaxAssetID ids.ID, +// ) (uint64, []uint32, bool) { +// if utxo.Asset.ID != avaxAssetID { +// // Only AVAX can be imported +// return 0, nil, false +// } + +// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) +// if !ok { +// // Can't import an unknown transfer output type +// return 0, nil, false +// } + +// inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) +// return out.Amt, inputSigIndices, ok +// } diff --git a/wallet/chain/c/builder_with_options.go b/wallet/chain/c/builder_with_options.go index 8416dddf9928..9b7ab8399484 100644 --- a/wallet/chain/c/builder_with_options.go +++ b/wallet/chain/c/builder_with_options.go @@ -3,81 +3,81 @@ package c -import ( - "math/big" +// import ( +// "math/big" - "github.com/ava-labs/coreth/plugin/evm" +// "github.com/ava-labs/coreth/plugin/evm" - ethcommon "github.com/ethereum/go-ethereum/common" +// ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) -var _ Builder = (*builderWithOptions)(nil) +// var _ Builder = (*builderWithOptions)(nil) -type builderWithOptions struct { - Builder - options []common.Option -} +// type builderWithOptions struct { +// Builder +// options []common.Option +// } -// NewBuilderWithOptions returns a new transaction builder that will use the -// given options by default. -// -// - [builder] is the builder that will be called to perform the underlying -// operations. -// - [options] will be provided to the builder in addition to the options -// provided in the method calls. -func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { - return &builderWithOptions{ - Builder: builder, - options: options, - } -} +// // NewBuilderWithOptions returns a new transaction builder that will use the +// // given options by default. +// // +// // - [builder] is the builder that will be called to perform the underlying +// // operations. +// // - [options] will be provided to the builder in addition to the options +// // provided in the method calls. +// func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { +// return &builderWithOptions{ +// Builder: builder, +// options: options, +// } +// } -func (b *builderWithOptions) GetBalance( - options ...common.Option, -) (*big.Int, error) { - return b.Builder.GetBalance( - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) GetBalance( +// options ...common.Option, +// ) (*big.Int, error) { +// return b.Builder.GetBalance( +// common.UnionOptions(b.options, options)..., +// ) +// } -func (b *builderWithOptions) GetImportableBalance( - chainID ids.ID, - options ...common.Option, -) (uint64, error) { - return b.Builder.GetImportableBalance( - chainID, - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) GetImportableBalance( +// chainID ids.ID, +// options ...common.Option, +// ) (uint64, error) { +// return b.Builder.GetImportableBalance( +// chainID, +// common.UnionOptions(b.options, options)..., +// ) +// } -func (b *builderWithOptions) NewImportTx( - chainID ids.ID, - to ethcommon.Address, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedImportTx, error) { - return b.Builder.NewImportTx( - chainID, - to, - baseFee, - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) NewImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedImportTx, error) { +// return b.Builder.NewImportTx( +// chainID, +// to, +// baseFee, +// common.UnionOptions(b.options, options)..., +// ) +// } -func (b *builderWithOptions) NewExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedExportTx, error) { - return b.Builder.NewExportTx( - chainID, - outputs, - baseFee, - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) NewExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedExportTx, error) { +// return b.Builder.NewExportTx( +// chainID, +// outputs, +// baseFee, +// common.UnionOptions(b.options, options)..., +// ) +// } diff --git a/wallet/chain/c/context.go b/wallet/chain/c/context.go index d506b42f81fa..1c01d8fb55c8 100644 --- a/wallet/chain/c/context.go +++ b/wallet/chain/c/context.go @@ -3,81 +3,81 @@ package c -import ( - stdcontext "context" +// import ( +// stdcontext "context" - "github.com/ava-labs/avalanchego/api/info" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/avm" -) +// "github.com/ava-labs/avalanchego/api/info" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/avm" +// ) -var _ Context = (*context)(nil) +// var _ Context = (*context)(nil) -type Context interface { - NetworkID() uint32 - BlockchainID() ids.ID - AVAXAssetID() ids.ID -} +// type Context interface { +// NetworkID() uint32 +// BlockchainID() ids.ID +// AVAXAssetID() ids.ID +// } -type context struct { - networkID uint32 - blockchainID ids.ID - avaxAssetID ids.ID -} +// type context struct { +// networkID uint32 +// blockchainID ids.ID +// avaxAssetID ids.ID +// } -func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { - infoClient := info.NewClient(uri) - xChainClient := avm.NewClient(uri, "X") - return NewContextFromClients(ctx, infoClient, xChainClient) -} +// func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { +// infoClient := info.NewClient(uri) +// xChainClient := avm.NewClient(uri, "X") +// return NewContextFromClients(ctx, infoClient, xChainClient) +// } -func NewContextFromClients( - ctx stdcontext.Context, - infoClient info.Client, - xChainClient avm.Client, -) (Context, error) { - networkID, err := infoClient.GetNetworkID(ctx) - if err != nil { - return nil, err - } +// func NewContextFromClients( +// ctx stdcontext.Context, +// infoClient info.Client, +// xChainClient avm.Client, +// ) (Context, error) { +// networkID, err := infoClient.GetNetworkID(ctx) +// if err != nil { +// return nil, err +// } - chainID, err := infoClient.GetBlockchainID(ctx, "C") - if err != nil { - return nil, err - } +// chainID, err := infoClient.GetBlockchainID(ctx, "C") +// if err != nil { +// return nil, err +// } - asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") - if err != nil { - return nil, err - } +// asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") +// if err != nil { +// return nil, err +// } - return NewContext( - networkID, - chainID, - asset.AssetID, - ), nil -} +// return NewContext( +// networkID, +// chainID, +// asset.AssetID, +// ), nil +// } -func NewContext( - networkID uint32, - blockchainID ids.ID, - avaxAssetID ids.ID, -) Context { - return &context{ - networkID: networkID, - blockchainID: blockchainID, - avaxAssetID: avaxAssetID, - } -} +// func NewContext( +// networkID uint32, +// blockchainID ids.ID, +// avaxAssetID ids.ID, +// ) Context { +// return &context{ +// networkID: networkID, +// blockchainID: blockchainID, +// avaxAssetID: avaxAssetID, +// } +// } -func (c *context) NetworkID() uint32 { - return c.networkID -} +// func (c *context) NetworkID() uint32 { +// return c.networkID +// } -func (c *context) BlockchainID() ids.ID { - return c.blockchainID -} +// func (c *context) BlockchainID() ids.ID { +// return c.blockchainID +// } -func (c *context) AVAXAssetID() ids.ID { - return c.avaxAssetID -} +// func (c *context) AVAXAssetID() ids.ID { +// return c.avaxAssetID +// } diff --git a/wallet/chain/c/signer.go b/wallet/chain/c/signer.go index 4fd85ed3b532..4bedc378234b 100644 --- a/wallet/chain/c/signer.go +++ b/wallet/chain/c/signer.go @@ -3,221 +3,221 @@ package c -import ( - "errors" - "fmt" - - stdcontext "context" - - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/crypto/keychain" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/hashing" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/components/verify" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" -) - -const version = 0 - -var ( - _ Signer = (*txSigner)(nil) - - errUnknownInputType = errors.New("unknown input type") - errUnknownCredentialType = errors.New("unknown credential type") - errUnknownOutputType = errors.New("unknown output type") - errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") - - emptySig [secp256k1.SignatureLen]byte -) - -type Signer interface { - SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) - SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error -} - -type EthKeychain interface { - // The returned Signer can provide a signature for [addr] - GetEth(addr ethcommon.Address) (keychain.Signer, bool) - // Returns the set of addresses for which the accessor keeps an associated - // signer - EthAddresses() set.Set[ethcommon.Address] -} - -type SignerBackend interface { - GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) -} - -type txSigner struct { - avaxKC keychain.Keychain - ethKC EthKeychain - backend SignerBackend -} - -func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { - return &txSigner{ - avaxKC: avaxKC, - ethKC: ethKC, - backend: backend, - } -} - -func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { - tx := &evm.Tx{UnsignedAtomicTx: utx} - return tx, s.SignAtomic(ctx, tx) -} - -func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { - switch utx := tx.UnsignedAtomicTx.(type) { - case *evm.UnsignedImportTx: - signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) - if err != nil { - return err - } - return sign(tx, true, signers) - case *evm.UnsignedExportTx: - signers := s.getExportSigners(utx.Ins) - return sign(tx, true, signers) - default: - return fmt.Errorf("%w: %T", errUnknownTxType, tx) - } -} - -func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { - txSigners := make([][]keychain.Signer, len(ins)) - for credIndex, transferInput := range ins { - input, ok := transferInput.In.(*secp256k1fx.TransferInput) - if !ok { - return nil, errUnknownInputType - } - - inputSigners := make([]keychain.Signer, len(input.SigIndices)) - txSigners[credIndex] = inputSigners - - utxoID := transferInput.InputID() - utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) - if err == database.ErrNotFound { - // If we don't have access to the UTXO, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - if err != nil { - return nil, err - } - - out, ok := utxo.Out.(*secp256k1fx.TransferOutput) - if !ok { - return nil, errUnknownOutputType - } - - for sigIndex, addrIndex := range input.SigIndices { - if addrIndex >= uint32(len(out.Addrs)) { - return nil, errInvalidUTXOSigIndex - } - - addr := out.Addrs[addrIndex] - key, ok := s.avaxKC.Get(addr) - if !ok { - // If we don't have access to the key, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - inputSigners[sigIndex] = key - } - } - return txSigners, nil -} - -func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { - txSigners := make([][]keychain.Signer, len(ins)) - for credIndex, input := range ins { - inputSigners := make([]keychain.Signer, 1) - txSigners[credIndex] = inputSigners - - key, ok := s.ethKC.GetEth(input.Address) - if !ok { - // If we don't have access to the key, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - inputSigners[0] = key - } - return txSigners -} - -// TODO: remove [signHash] after the ledger supports signing all transactions. -func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { - unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) - if err != nil { - return fmt.Errorf("couldn't marshal unsigned tx: %w", err) - } - unsignedHash := hashing.ComputeHash256(unsignedBytes) - - if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { - tx.Creds = make([]verify.Verifiable, expectedLen) - } - - sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) - for credIndex, inputSigners := range txSigners { - credIntf := tx.Creds[credIndex] - if credIntf == nil { - credIntf = &secp256k1fx.Credential{} - tx.Creds[credIndex] = credIntf - } - - cred, ok := credIntf.(*secp256k1fx.Credential) - if !ok { - return errUnknownCredentialType - } - if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { - cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) - } - - for sigIndex, signer := range inputSigners { - if signer == nil { - // If we don't have access to the key, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - addr := signer.Address() - if sig := cred.Sigs[sigIndex]; sig != emptySig { - // If this signature has already been populated, we can just - // copy the needed signature for the future. - sigCache[addr] = sig - continue - } - - if sig, exists := sigCache[addr]; exists { - // If this key has already produced a signature, we can just - // copy the previous signature. - cred.Sigs[sigIndex] = sig - continue - } - - var sig []byte - if signHash { - sig, err = signer.SignHash(unsignedHash) - } else { - sig, err = signer.Sign(unsignedBytes) - } - if err != nil { - return fmt.Errorf("problem signing tx: %w", err) - } - copy(cred.Sigs[sigIndex][:], sig) - sigCache[addr] = cred.Sigs[sigIndex] - } - } - - signedBytes, err := evm.Codec.Marshal(version, tx) - if err != nil { - return fmt.Errorf("couldn't marshal tx: %w", err) - } - tx.Initialize(unsignedBytes, signedBytes) - return nil -} +// import ( +// "errors" +// "fmt" + +// stdcontext "context" + +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/database" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils/crypto/keychain" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/hashing" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/components/verify" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// ) + +// const version = 0 + +// var ( +// _ Signer = (*txSigner)(nil) + +// errUnknownInputType = errors.New("unknown input type") +// errUnknownCredentialType = errors.New("unknown credential type") +// errUnknownOutputType = errors.New("unknown output type") +// errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") + +// emptySig [secp256k1.SignatureLen]byte +// ) + +// type Signer interface { +// SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) +// SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error +// } + +// type EthKeychain interface { +// // The returned Signer can provide a signature for [addr] +// GetEth(addr ethcommon.Address) (keychain.Signer, bool) +// // Returns the set of addresses for which the accessor keeps an associated +// // signer +// EthAddresses() set.Set[ethcommon.Address] +// } + +// type SignerBackend interface { +// GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) +// } + +// type txSigner struct { +// avaxKC keychain.Keychain +// ethKC EthKeychain +// backend SignerBackend +// } + +// func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { +// return &txSigner{ +// avaxKC: avaxKC, +// ethKC: ethKC, +// backend: backend, +// } +// } + +// func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { +// tx := &evm.Tx{UnsignedAtomicTx: utx} +// return tx, s.SignAtomic(ctx, tx) +// } + +// func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { +// switch utx := tx.UnsignedAtomicTx.(type) { +// case *evm.UnsignedImportTx: +// signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) +// if err != nil { +// return err +// } +// return sign(tx, true, signers) +// case *evm.UnsignedExportTx: +// signers := s.getExportSigners(utx.Ins) +// return sign(tx, true, signers) +// default: +// return fmt.Errorf("%w: %T", errUnknownTxType, tx) +// } +// } + +// func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { +// txSigners := make([][]keychain.Signer, len(ins)) +// for credIndex, transferInput := range ins { +// input, ok := transferInput.In.(*secp256k1fx.TransferInput) +// if !ok { +// return nil, errUnknownInputType +// } + +// inputSigners := make([]keychain.Signer, len(input.SigIndices)) +// txSigners[credIndex] = inputSigners + +// utxoID := transferInput.InputID() +// utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) +// if err == database.ErrNotFound { +// // If we don't have access to the UTXO, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// if err != nil { +// return nil, err +// } + +// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) +// if !ok { +// return nil, errUnknownOutputType +// } + +// for sigIndex, addrIndex := range input.SigIndices { +// if addrIndex >= uint32(len(out.Addrs)) { +// return nil, errInvalidUTXOSigIndex +// } + +// addr := out.Addrs[addrIndex] +// key, ok := s.avaxKC.Get(addr) +// if !ok { +// // If we don't have access to the key, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// inputSigners[sigIndex] = key +// } +// } +// return txSigners, nil +// } + +// func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { +// txSigners := make([][]keychain.Signer, len(ins)) +// for credIndex, input := range ins { +// inputSigners := make([]keychain.Signer, 1) +// txSigners[credIndex] = inputSigners + +// key, ok := s.ethKC.GetEth(input.Address) +// if !ok { +// // If we don't have access to the key, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// inputSigners[0] = key +// } +// return txSigners +// } + +// // TODO: remove [signHash] after the ledger supports signing all transactions. +// func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { +// unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) +// if err != nil { +// return fmt.Errorf("couldn't marshal unsigned tx: %w", err) +// } +// unsignedHash := hashing.ComputeHash256(unsignedBytes) + +// if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { +// tx.Creds = make([]verify.Verifiable, expectedLen) +// } + +// sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) +// for credIndex, inputSigners := range txSigners { +// credIntf := tx.Creds[credIndex] +// if credIntf == nil { +// credIntf = &secp256k1fx.Credential{} +// tx.Creds[credIndex] = credIntf +// } + +// cred, ok := credIntf.(*secp256k1fx.Credential) +// if !ok { +// return errUnknownCredentialType +// } +// if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { +// cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) +// } + +// for sigIndex, signer := range inputSigners { +// if signer == nil { +// // If we don't have access to the key, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// addr := signer.Address() +// if sig := cred.Sigs[sigIndex]; sig != emptySig { +// // If this signature has already been populated, we can just +// // copy the needed signature for the future. +// sigCache[addr] = sig +// continue +// } + +// if sig, exists := sigCache[addr]; exists { +// // If this key has already produced a signature, we can just +// // copy the previous signature. +// cred.Sigs[sigIndex] = sig +// continue +// } + +// var sig []byte +// if signHash { +// sig, err = signer.SignHash(unsignedHash) +// } else { +// sig, err = signer.Sign(unsignedBytes) +// } +// if err != nil { +// return fmt.Errorf("problem signing tx: %w", err) +// } +// copy(cred.Sigs[sigIndex][:], sig) +// sigCache[addr] = cred.Sigs[sigIndex] +// } +// } + +// signedBytes, err := evm.Codec.Marshal(version, tx) +// if err != nil { +// return fmt.Errorf("couldn't marshal tx: %w", err) +// } +// tx.Initialize(unsignedBytes, signedBytes) +// return nil +// } diff --git a/wallet/chain/c/wallet.go b/wallet/chain/c/wallet.go index fb1a83d53dad..ebee50a9a958 100644 --- a/wallet/chain/c/wallet.go +++ b/wallet/chain/c/wallet.go @@ -3,204 +3,204 @@ package c -import ( - "errors" - "math/big" - "time" - - "github.com/ava-labs/coreth/ethclient" - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var ( - _ Wallet = (*wallet)(nil) - - errNotCommitted = errors.New("not committed") -) - -type Wallet interface { - Context - - // Builder returns the builder that will be used to create the transactions. - Builder() Builder - - // Signer returns the signer that will be used to sign the transactions. - Signer() Signer - - // IssueImportTx creates, signs, and issues an import transaction that - // attempts to consume all the available UTXOs and import the funds to [to]. - // - // - [chainID] specifies the chain to be importing funds from. - // - [to] specifies where to send the imported funds to. - IssueImportTx( - chainID ids.ID, - to ethcommon.Address, - options ...common.Option, - ) (*evm.Tx, error) - - // IssueExportTx creates, signs, and issues an export transaction that - // attempts to send all the provided [outputs] to the requested [chainID]. - // - // - [chainID] specifies the chain to be exporting the funds to. - // - [outputs] specifies the outputs to send to the [chainID]. - IssueExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - options ...common.Option, - ) (*evm.Tx, error) - - // IssueUnsignedTx signs and issues the unsigned tx. - IssueUnsignedAtomicTx( - utx evm.UnsignedAtomicTx, - options ...common.Option, - ) (*evm.Tx, error) - - // IssueAtomicTx issues the signed tx. - IssueAtomicTx( - tx *evm.Tx, - options ...common.Option, - ) error -} - -func NewWallet( - builder Builder, - signer Signer, - avaxClient evm.Client, - ethClient ethclient.Client, - backend Backend, -) Wallet { - return &wallet{ - Backend: backend, - builder: builder, - signer: signer, - avaxClient: avaxClient, - ethClient: ethClient, - } -} - -type wallet struct { - Backend - builder Builder - signer Signer - avaxClient evm.Client - ethClient ethclient.Client -} - -func (w *wallet) Builder() Builder { - return w.builder -} - -func (w *wallet) Signer() Signer { - return w.signer -} - -func (w *wallet) IssueImportTx( - chainID ids.ID, - to ethcommon.Address, - options ...common.Option, -) (*evm.Tx, error) { - baseFee, err := w.baseFee(options) - if err != nil { - return nil, err - } - - utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) - if err != nil { - return nil, err - } - return w.IssueUnsignedAtomicTx(utx, options...) -} - -func (w *wallet) IssueExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - options ...common.Option, -) (*evm.Tx, error) { - baseFee, err := w.baseFee(options) - if err != nil { - return nil, err - } - - utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) - if err != nil { - return nil, err - } - return w.IssueUnsignedAtomicTx(utx, options...) -} - -func (w *wallet) IssueUnsignedAtomicTx( - utx evm.UnsignedAtomicTx, - options ...common.Option, -) (*evm.Tx, error) { - ops := common.NewOptions(options) - ctx := ops.Context() - tx, err := w.signer.SignUnsignedAtomic(ctx, utx) - if err != nil { - return nil, err - } - - return tx, w.IssueAtomicTx(tx, options...) -} - -func (w *wallet) IssueAtomicTx( - tx *evm.Tx, - options ...common.Option, -) error { - ops := common.NewOptions(options) - ctx := ops.Context() - txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) - if err != nil { - return err - } - - if f := ops.PostIssuanceFunc(); f != nil { - f(txID) - } - - if ops.AssumeDecided() { - return w.Backend.AcceptAtomicTx(ctx, tx) - } - - pollFrequency := ops.PollFrequency() - ticker := time.NewTicker(pollFrequency) - defer ticker.Stop() - - for { - status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) - if err != nil { - return err - } - - switch status { - case evm.Accepted: - return w.Backend.AcceptAtomicTx(ctx, tx) - case evm.Dropped, evm.Unknown: - return errNotCommitted - } - - // The tx is Processing. - - select { - case <-ticker.C: - case <-ctx.Done(): - return ctx.Err() - } - } -} - -func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { - ops := common.NewOptions(options) - baseFee := ops.BaseFee(nil) - if baseFee != nil { - return baseFee, nil - } - - ctx := ops.Context() - return w.ethClient.EstimateBaseFee(ctx) -} +// import ( +// "errors" +// "math/big" +// "time" + +// "github.com/ava-labs/coreth/ethclient" +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var ( +// _ Wallet = (*wallet)(nil) + +// errNotCommitted = errors.New("not committed") +// ) + +// type Wallet interface { +// Context + +// // Builder returns the builder that will be used to create the transactions. +// Builder() Builder + +// // Signer returns the signer that will be used to sign the transactions. +// Signer() Signer + +// // IssueImportTx creates, signs, and issues an import transaction that +// // attempts to consume all the available UTXOs and import the funds to [to]. +// // +// // - [chainID] specifies the chain to be importing funds from. +// // - [to] specifies where to send the imported funds to. +// IssueImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// options ...common.Option, +// ) (*evm.Tx, error) + +// // IssueExportTx creates, signs, and issues an export transaction that +// // attempts to send all the provided [outputs] to the requested [chainID]. +// // +// // - [chainID] specifies the chain to be exporting the funds to. +// // - [outputs] specifies the outputs to send to the [chainID]. +// IssueExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// options ...common.Option, +// ) (*evm.Tx, error) + +// // IssueUnsignedTx signs and issues the unsigned tx. +// IssueUnsignedAtomicTx( +// utx evm.UnsignedAtomicTx, +// options ...common.Option, +// ) (*evm.Tx, error) + +// // IssueAtomicTx issues the signed tx. +// IssueAtomicTx( +// tx *evm.Tx, +// options ...common.Option, +// ) error +// } + +// func NewWallet( +// builder Builder, +// signer Signer, +// avaxClient evm.Client, +// ethClient ethclient.Client, +// backend Backend, +// ) Wallet { +// return &wallet{ +// Backend: backend, +// builder: builder, +// signer: signer, +// avaxClient: avaxClient, +// ethClient: ethClient, +// } +// } + +// type wallet struct { +// Backend +// builder Builder +// signer Signer +// avaxClient evm.Client +// ethClient ethclient.Client +// } + +// func (w *wallet) Builder() Builder { +// return w.builder +// } + +// func (w *wallet) Signer() Signer { +// return w.signer +// } + +// func (w *wallet) IssueImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// options ...common.Option, +// ) (*evm.Tx, error) { +// baseFee, err := w.baseFee(options) +// if err != nil { +// return nil, err +// } + +// utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) +// if err != nil { +// return nil, err +// } +// return w.IssueUnsignedAtomicTx(utx, options...) +// } + +// func (w *wallet) IssueExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// options ...common.Option, +// ) (*evm.Tx, error) { +// baseFee, err := w.baseFee(options) +// if err != nil { +// return nil, err +// } + +// utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) +// if err != nil { +// return nil, err +// } +// return w.IssueUnsignedAtomicTx(utx, options...) +// } + +// func (w *wallet) IssueUnsignedAtomicTx( +// utx evm.UnsignedAtomicTx, +// options ...common.Option, +// ) (*evm.Tx, error) { +// ops := common.NewOptions(options) +// ctx := ops.Context() +// tx, err := w.signer.SignUnsignedAtomic(ctx, utx) +// if err != nil { +// return nil, err +// } + +// return tx, w.IssueAtomicTx(tx, options...) +// } + +// func (w *wallet) IssueAtomicTx( +// tx *evm.Tx, +// options ...common.Option, +// ) error { +// ops := common.NewOptions(options) +// ctx := ops.Context() +// txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) +// if err != nil { +// return err +// } + +// if f := ops.PostIssuanceFunc(); f != nil { +// f(txID) +// } + +// if ops.AssumeDecided() { +// return w.Backend.AcceptAtomicTx(ctx, tx) +// } + +// pollFrequency := ops.PollFrequency() +// ticker := time.NewTicker(pollFrequency) +// defer ticker.Stop() + +// for { +// status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) +// if err != nil { +// return err +// } + +// switch status { +// case evm.Accepted: +// return w.Backend.AcceptAtomicTx(ctx, tx) +// case evm.Dropped, evm.Unknown: +// return errNotCommitted +// } + +// // The tx is Processing. + +// select { +// case <-ticker.C: +// case <-ctx.Done(): +// return ctx.Err() +// } +// } +// } + +// func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { +// ops := common.NewOptions(options) +// baseFee := ops.BaseFee(nil) +// if baseFee != nil { +// return baseFee, nil +// } + +// ctx := ops.Context() +// return w.ethClient.EstimateBaseFee(ctx) +// } diff --git a/wallet/chain/c/wallet_with_options.go b/wallet/chain/c/wallet_with_options.go index 7d6193683d49..fd69a6d4fd02 100644 --- a/wallet/chain/c/wallet_with_options.go +++ b/wallet/chain/c/wallet_with_options.go @@ -3,80 +3,80 @@ package c -import ( - "github.com/ava-labs/coreth/plugin/evm" +// import ( +// "github.com/ava-labs/coreth/plugin/evm" - ethcommon "github.com/ethereum/go-ethereum/common" +// ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) -var _ Wallet = (*walletWithOptions)(nil) +// var _ Wallet = (*walletWithOptions)(nil) -func NewWalletWithOptions( - wallet Wallet, - options ...common.Option, -) Wallet { - return &walletWithOptions{ - Wallet: wallet, - options: options, - } -} +// func NewWalletWithOptions( +// wallet Wallet, +// options ...common.Option, +// ) Wallet { +// return &walletWithOptions{ +// Wallet: wallet, +// options: options, +// } +// } -type walletWithOptions struct { - Wallet - options []common.Option -} +// type walletWithOptions struct { +// Wallet +// options []common.Option +// } -func (w *walletWithOptions) Builder() Builder { - return NewBuilderWithOptions( - w.Wallet.Builder(), - w.options..., - ) -} +// func (w *walletWithOptions) Builder() Builder { +// return NewBuilderWithOptions( +// w.Wallet.Builder(), +// w.options..., +// ) +// } -func (w *walletWithOptions) IssueImportTx( - chainID ids.ID, - to ethcommon.Address, - options ...common.Option, -) (*evm.Tx, error) { - return w.Wallet.IssueImportTx( - chainID, - to, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// options ...common.Option, +// ) (*evm.Tx, error) { +// return w.Wallet.IssueImportTx( +// chainID, +// to, +// common.UnionOptions(w.options, options)..., +// ) +// } -func (w *walletWithOptions) IssueExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - options ...common.Option, -) (*evm.Tx, error) { - return w.Wallet.IssueExportTx( - chainID, - outputs, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// options ...common.Option, +// ) (*evm.Tx, error) { +// return w.Wallet.IssueExportTx( +// chainID, +// outputs, +// common.UnionOptions(w.options, options)..., +// ) +// } -func (w *walletWithOptions) IssueUnsignedAtomicTx( - utx evm.UnsignedAtomicTx, - options ...common.Option, -) (*evm.Tx, error) { - return w.Wallet.IssueUnsignedAtomicTx( - utx, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueUnsignedAtomicTx( +// utx evm.UnsignedAtomicTx, +// options ...common.Option, +// ) (*evm.Tx, error) { +// return w.Wallet.IssueUnsignedAtomicTx( +// utx, +// common.UnionOptions(w.options, options)..., +// ) +// } -func (w *walletWithOptions) IssueAtomicTx( - tx *evm.Tx, - options ...common.Option, -) error { - return w.Wallet.IssueAtomicTx( - tx, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueAtomicTx( +// tx *evm.Tx, +// options ...common.Option, +// ) error { +// return w.Wallet.IssueAtomicTx( +// tx, +// common.UnionOptions(w.options, options)..., +// ) +// } diff --git a/wallet/subnet/primary/api.go b/wallet/subnet/primary/api.go index 3ac72c217884..402b79989d17 100644 --- a/wallet/subnet/primary/api.go +++ b/wallet/subnet/primary/api.go @@ -5,12 +5,12 @@ package primary import ( "context" - "fmt" + // "fmt" - "github.com/ava-labs/coreth/ethclient" - "github.com/ava-labs/coreth/plugin/evm" + // "github.com/ava-labs/coreth/ethclient" + // "github.com/ava-labs/coreth/plugin/evm" - "github.com/ethereum/go-ethereum/common" + // "github.com/ethereum/go-ethereum/common" "github.com/ava-labs/avalanchego/api/info" "github.com/ava-labs/avalanchego/codec" @@ -22,7 +22,8 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm" "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/wallet/chain/c" + + // "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" ) @@ -59,9 +60,9 @@ type AVAXState struct { PCTX p.Context XClient avm.Client XCTX x.Context - CClient evm.Client - CCTX c.Context - UTXOs UTXOs + // CClient evm.Client + // CCTX c.Context + UTXOs UTXOs } func FetchState( @@ -75,7 +76,7 @@ func FetchState( infoClient := info.NewClient(uri) pClient := platformvm.NewClient(uri) xClient := avm.NewClient(uri, "X") - cClient := evm.NewCChainClient(uri) + // cClient := evm.NewCChainClient(uri) pCTX, err := p.NewContextFromClients(ctx, infoClient, xClient) if err != nil { @@ -87,10 +88,10 @@ func FetchState( return nil, err } - cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) - if err != nil { - return nil, err - } + // cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) + // if err != nil { + // return nil, err + // } utxos := NewUTXOs() addrList := addrs.List() @@ -109,11 +110,11 @@ func FetchState( client: xClient, codec: x.Parser.Codec(), }, - { - id: cCTX.BlockchainID(), - client: cClient, - codec: evm.Codec, - }, + // { + // id: cCTX.BlockchainID(), + // client: cClient, + // codec: evm.Codec, + // }, } for _, destinationChain := range chains { for _, sourceChain := range chains { @@ -136,52 +137,52 @@ func FetchState( PCTX: pCTX, XClient: xClient, XCTX: xCTX, - CClient: cClient, - CCTX: cCTX, - UTXOs: utxos, + // CClient: cClient, + // CCTX: cCTX, + UTXOs: utxos, }, nil } -type EthState struct { - Client ethclient.Client - Accounts map[common.Address]*c.Account -} - -func FetchEthState( - ctx context.Context, - uri string, - addrs set.Set[common.Address], -) (*EthState, error) { - path := fmt.Sprintf( - "%s/ext/%s/C/rpc", - uri, - constants.ChainAliasPrefix, - ) - client, err := ethclient.Dial(path) - if err != nil { - return nil, err - } - - accounts := make(map[common.Address]*c.Account, addrs.Len()) - for addr := range addrs { - balance, err := client.BalanceAt(ctx, addr, nil) - if err != nil { - return nil, err - } - nonce, err := client.NonceAt(ctx, addr, nil) - if err != nil { - return nil, err - } - accounts[addr] = &c.Account{ - Balance: balance, - Nonce: nonce, - } - } - return &EthState{ - Client: client, - Accounts: accounts, - }, nil -} +// type EthState struct { +// Client ethclient.Client +// Accounts map[common.Address]*c.Account +// } + +// func FetchEthState( +// ctx context.Context, +// uri string, +// addrs set.Set[common.Address], +// ) (*EthState, error) { +// path := fmt.Sprintf( +// "%s/ext/%s/C/rpc", +// uri, +// constants.ChainAliasPrefix, +// ) +// client, err := ethclient.Dial(path) +// if err != nil { +// return nil, err +// } + +// accounts := make(map[common.Address]*c.Account, addrs.Len()) +// for addr := range addrs { +// balance, err := client.BalanceAt(ctx, addr, nil) +// if err != nil { +// return nil, err +// } +// nonce, err := client.NonceAt(ctx, addr, nil) +// if err != nil { +// return nil, err +// } +// accounts[addr] = &c.Account{ +// Balance: balance, +// Nonce: nonce, +// } +// } +// return &EthState{ +// Client: client, +// Accounts: accounts, +// }, nil +// } // AddAllUTXOs fetches all the UTXOs referenced by [addresses] that were sent // from [sourceChainID] to [destinationChainID] from the [client]. It then uses diff --git a/wallet/subnet/primary/example_test.go b/wallet/subnet/primary/example_test.go index 483c049d4ac0..4a73e8c070b2 100644 --- a/wallet/subnet/primary/example_test.go +++ b/wallet/subnet/primary/example_test.go @@ -30,7 +30,7 @@ func ExampleWallet() { wallet, err := MakeWallet(ctx, &WalletConfig{ URI: LocalAPIURI, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet with: %s\n", err) diff --git a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go index d5e8ce422307..21c081d2982b 100644 --- a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go @@ -46,9 +46,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/add-primary-validator/main.go b/wallet/subnet/primary/examples/add-primary-validator/main.go index a56dae23db3a..13c28f995f63 100644 --- a/wallet/subnet/primary/examples/add-primary-validator/main.go +++ b/wallet/subnet/primary/examples/add-primary-validator/main.go @@ -45,7 +45,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/c-chain-export/main.go b/wallet/subnet/primary/examples/c-chain-export/main.go index fec55c899feb..a6b9a0c810b8 100644 --- a/wallet/subnet/primary/examples/c-chain-export/main.go +++ b/wallet/subnet/primary/examples/c-chain-export/main.go @@ -3,70 +3,70 @@ package main -import ( - "context" - "log" - "time" +// import ( +// "context" +// "log" +// "time" - "github.com/ava-labs/avalanchego/genesis" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary" -) +// "github.com/ava-labs/avalanchego/genesis" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary" +// ) -func main() { - key := genesis.EWOQKey - uri := primary.LocalAPIURI - kc := secp256k1fx.NewKeychain(key) - avaxAddr := key.Address() +// func main() { +// key := genesis.EWOQKey +// uri := primary.LocalAPIURI +// kc := secp256k1fx.NewKeychain(key) +// avaxAddr := key.Address() - ctx := context.Background() +// ctx := context.Background() - // MakeWallet fetches the available UTXOs owned by [kc] on the network that - // [uri] is hosting. - walletSyncStartTime := time.Now() - wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, - }) - if err != nil { - log.Fatalf("failed to initialize wallet: %s\n", err) - } - log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) +// // MakeWallet fetches the available UTXOs owned by [kc] on the network that +// // [uri] is hosting. +// walletSyncStartTime := time.Now() +// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ +// URI: uri, +// AVAXKeychain: kc, +// EthKeychain: kc, +// }) +// if err != nil { +// log.Fatalf("failed to initialize wallet: %s\n", err) +// } +// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) - // Get the P-chain wallet - pWallet := wallet.P() - cWallet := wallet.C() +// // Get the P-chain wallet +// pWallet := wallet.P() +// cWallet := wallet.C() - // Pull out useful constants to use when issuing transactions. - cChainID := cWallet.BlockchainID() - owner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - avaxAddr, - }, - } +// // Pull out useful constants to use when issuing transactions. +// cChainID := cWallet.BlockchainID() +// owner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// avaxAddr, +// }, +// } - exportStartTime := time.Now() - exportTx, err := cWallet.IssueExportTx( - constants.PlatformChainID, - []*secp256k1fx.TransferOutput{{ - Amt: units.Avax, - OutputOwners: owner, - }}, - ) - if err != nil { - log.Fatalf("failed to issue export transaction: %s\n", err) - } - log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) +// exportStartTime := time.Now() +// exportTx, err := cWallet.IssueExportTx( +// constants.PlatformChainID, +// []*secp256k1fx.TransferOutput{{ +// Amt: units.Avax, +// OutputOwners: owner, +// }}, +// ) +// if err != nil { +// log.Fatalf("failed to issue export transaction: %s\n", err) +// } +// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) - importStartTime := time.Now() - importTx, err := pWallet.IssueImportTx(cChainID, &owner) - if err != nil { - log.Fatalf("failed to issue import transaction: %s\n", err) - } - log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) -} +// importStartTime := time.Now() +// importTx, err := pWallet.IssueImportTx(cChainID, &owner) +// if err != nil { +// log.Fatalf("failed to issue import transaction: %s\n", err) +// } +// log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) +// } diff --git a/wallet/subnet/primary/examples/c-chain-import/main.go b/wallet/subnet/primary/examples/c-chain-import/main.go index b4dc4e603eb3..2d9b8a244cb0 100644 --- a/wallet/subnet/primary/examples/c-chain-import/main.go +++ b/wallet/subnet/primary/examples/c-chain-import/main.go @@ -3,75 +3,75 @@ package main -import ( - "context" - "log" - "time" +// import ( +// "context" +// "log" +// "time" - "github.com/ava-labs/coreth/plugin/evm" +// "github.com/ava-labs/coreth/plugin/evm" - "github.com/ava-labs/avalanchego/genesis" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary" -) +// "github.com/ava-labs/avalanchego/genesis" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary" +// ) -func main() { - key := genesis.EWOQKey - uri := primary.LocalAPIURI - kc := secp256k1fx.NewKeychain(key) - avaxAddr := key.Address() - ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) +// func main() { +// key := genesis.EWOQKey +// uri := primary.LocalAPIURI +// kc := secp256k1fx.NewKeychain(key) +// avaxAddr := key.Address() +// ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) - ctx := context.Background() +// ctx := context.Background() - // MakeWallet fetches the available UTXOs owned by [kc] on the network that - // [uri] is hosting. - walletSyncStartTime := time.Now() - wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, - }) - if err != nil { - log.Fatalf("failed to initialize wallet: %s\n", err) - } - log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) +// // MakeWallet fetches the available UTXOs owned by [kc] on the network that +// // [uri] is hosting. +// walletSyncStartTime := time.Now() +// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ +// URI: uri, +// AVAXKeychain: kc, +// EthKeychain: kc, +// }) +// if err != nil { +// log.Fatalf("failed to initialize wallet: %s\n", err) +// } +// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) - // Get the P-chain wallet - pWallet := wallet.P() - cWallet := wallet.C() +// // Get the P-chain wallet +// pWallet := wallet.P() +// cWallet := wallet.C() - // Pull out useful constants to use when issuing transactions. - cChainID := cWallet.BlockchainID() - avaxAssetID := cWallet.AVAXAssetID() - owner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - avaxAddr, - }, - } +// // Pull out useful constants to use when issuing transactions. +// cChainID := cWallet.BlockchainID() +// avaxAssetID := cWallet.AVAXAssetID() +// owner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// avaxAddr, +// }, +// } - exportStartTime := time.Now() - exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ - Asset: avax.Asset{ID: avaxAssetID}, - Out: &secp256k1fx.TransferOutput{ - Amt: units.Avax, - OutputOwners: owner, - }, - }}) - if err != nil { - log.Fatalf("failed to issue export transaction: %s\n", err) - } - log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) +// exportStartTime := time.Now() +// exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ +// Asset: avax.Asset{ID: avaxAssetID}, +// Out: &secp256k1fx.TransferOutput{ +// Amt: units.Avax, +// OutputOwners: owner, +// }, +// }}) +// if err != nil { +// log.Fatalf("failed to issue export transaction: %s\n", err) +// } +// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) - importStartTime := time.Now() - importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) - if err != nil { - log.Fatalf("failed to issue import transaction: %s\n", err) - } - log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) -} +// importStartTime := time.Now() +// importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) +// if err != nil { +// log.Fatalf("failed to issue import transaction: %s\n", err) +// } +// log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) +// } diff --git a/wallet/subnet/primary/examples/create-asset/main.go b/wallet/subnet/primary/examples/create-asset/main.go index 30804f083df6..0bccfbb5fc52 100644 --- a/wallet/subnet/primary/examples/create-asset/main.go +++ b/wallet/subnet/primary/examples/create-asset/main.go @@ -30,7 +30,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-chain/main.go b/wallet/subnet/primary/examples/create-chain/main.go index 5e6898a1b649..521a3cca53cf 100644 --- a/wallet/subnet/primary/examples/create-chain/main.go +++ b/wallet/subnet/primary/examples/create-chain/main.go @@ -41,9 +41,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/create-locked-stakeable/main.go b/wallet/subnet/primary/examples/create-locked-stakeable/main.go index e688968e9e8a..92f1b5cb0e1b 100644 --- a/wallet/subnet/primary/examples/create-locked-stakeable/main.go +++ b/wallet/subnet/primary/examples/create-locked-stakeable/main.go @@ -39,7 +39,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-subnet/main.go b/wallet/subnet/primary/examples/create-subnet/main.go index add98ea7931c..3e8d69bc016a 100644 --- a/wallet/subnet/primary/examples/create-subnet/main.go +++ b/wallet/subnet/primary/examples/create-subnet/main.go @@ -28,7 +28,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/remove-subnet-validator/main.go b/wallet/subnet/primary/examples/remove-subnet-validator/main.go index 2842c7c0a790..46f4b85124db 100644 --- a/wallet/subnet/primary/examples/remove-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/remove-subnet-validator/main.go @@ -38,9 +38,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/wallet.go b/wallet/subnet/primary/wallet.go index 54de390d029c..ae5e4202a099 100644 --- a/wallet/subnet/primary/wallet.go +++ b/wallet/subnet/primary/wallet.go @@ -11,7 +11,8 @@ import ( "github.com/ava-labs/avalanchego/utils/crypto/keychain" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/wallet/chain/c" + + // "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" @@ -23,13 +24,13 @@ var _ Wallet = (*wallet)(nil) type Wallet interface { P() p.Wallet X() x.Wallet - C() c.Wallet + // C() c.Wallet } type wallet struct { p p.Wallet x x.Wallet - c c.Wallet + // c c.Wallet } func (w *wallet) P() p.Wallet { @@ -40,16 +41,16 @@ func (w *wallet) X() x.Wallet { return w.x } -func (w *wallet) C() c.Wallet { - return w.c -} +// func (w *wallet) C() c.Wallet { +// return w.c +// } // Creates a new default wallet -func NewWallet(p p.Wallet, x x.Wallet, c c.Wallet) Wallet { +func NewWallet(p p.Wallet, x x.Wallet /*, c c.Wallet*/) Wallet { return &wallet{ p: p, x: x, - c: c, + // c: c, } } @@ -58,7 +59,7 @@ func NewWalletWithOptions(w Wallet, options ...common.Option) Wallet { return NewWallet( p.NewWalletWithOptions(w.P(), options...), x.NewWalletWithOptions(w.X(), options...), - c.NewWalletWithOptions(w.C(), options...), + // c.NewWalletWithOptions(w.C(), options...), ) } @@ -67,7 +68,7 @@ type WalletConfig struct { URI string // required // Keys to use for signing all transactions. AVAXKeychain keychain.Keychain // required - EthKeychain c.EthKeychain // required + // EthKeychain c.EthKeychain // required // Set of P-chain transactions that the wallet should know about to be able // to generate transactions. PChainTxs map[ids.ID]*txs.Tx // optional @@ -93,11 +94,11 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { return nil, err } - ethAddrs := config.EthKeychain.EthAddresses() - ethState, err := FetchEthState(ctx, config.URI, ethAddrs) - if err != nil { - return nil, err - } + // ethAddrs := config.EthKeychain.EthAddresses() + // ethState, err := FetchEthState(ctx, config.URI, ethAddrs) + // if err != nil { + // return nil, err + // } pChainTxs := config.PChainTxs if pChainTxs == nil { @@ -127,15 +128,15 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { xBuilder := x.NewBuilder(avaxAddrs, xBackend) xSigner := x.NewSigner(config.AVAXKeychain, xBackend) - cChainID := avaxState.CCTX.BlockchainID() - cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) - cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) - cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) - cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) + // cChainID := avaxState.CCTX.BlockchainID() + // cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) + // cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) + // cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) + // cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) return NewWallet( p.NewWallet(pBuilder, pSigner, avaxState.PClient, pBackend), x.NewWallet(xBuilder, xSigner, avaxState.XClient, xBackend), - c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), + // c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), ), nil } From b638c4405ce23bf3ccb89d240ff50c6fcd5ceb11 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 26 Oct 2023 15:17:16 +0200 Subject: [PATCH 04/36] bumped coreth version --- go.mod | 25 + go.sum | 76 ++ node/node.go | 4 +- tests/e2e/c/dynamic_fees.go | 328 ++++---- tests/e2e/c/interchain_workflow.go | 322 +++---- tests/e2e/e2e.go | 124 ++- tests/e2e/p/interchain_workflow.go | 446 +++++----- tests/e2e/x/interchain_workflow.go | 298 +++---- tests/fixture/testnet/config.go | 56 +- vms/example/xsvm/cmd/chain/create/cmd.go | 6 +- wallet/chain/c/backend.go | 300 +++---- wallet/chain/c/builder.go | 792 +++++++++--------- wallet/chain/c/builder_with_options.go | 136 +-- wallet/chain/c/context.go | 130 +-- wallet/chain/c/signer.go | 436 +++++----- wallet/chain/c/wallet.go | 402 ++++----- wallet/chain/c/wallet_with_options.go | 134 +-- wallet/subnet/primary/api.go | 123 ++- wallet/subnet/primary/example_test.go | 2 +- .../add-permissioned-subnet-validator/main.go | 6 +- .../examples/add-primary-validator/main.go | 2 +- .../primary/examples/c-chain-export/main.go | 118 +-- .../primary/examples/c-chain-import/main.go | 126 +-- .../primary/examples/create-asset/main.go | 2 +- .../primary/examples/create-chain/main.go | 6 +- .../examples/create-locked-stakeable/main.go | 2 +- .../primary/examples/create-subnet/main.go | 2 +- .../examples/remove-subnet-validator/main.go | 6 +- wallet/subnet/primary/wallet.go | 43 +- 29 files changed, 2275 insertions(+), 2178 deletions(-) diff --git a/go.mod b/go.mod index 40d59d0cb294..ae9ea2a12051 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/DataDog/zstd v1.5.2 github.com/Microsoft/go-winio v0.5.2 github.com/NYTimes/gziphandler v1.1.1 + github.com/ava-labs/coreth v0.12.7-0.20231026130315-648dfa6abecd github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 github.com/btcsuite/btcd/btcutil v1.1.3 github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 @@ -71,6 +72,7 @@ require ( require ( github.com/BurntSushi/toml v1.2.1 // indirect + github.com/VictoriaMetrics/fastcache v1.10.0 // indirect github.com/benbjohnson/clock v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect @@ -79,26 +81,44 @@ require ( github.com/cockroachdb/errors v1.9.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/redact v1.1.3 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set/v2 v2.1.0 // indirect + github.com/dlclark/regexp2 v1.7.0 // indirect + github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect + github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/frankban/quicktest v1.14.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect + github.com/go-stack/stack v1.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/go-cmp v0.5.9 // indirect + github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 // indirect + github.com/hashicorp/go-bexpr v0.1.10 // indirect + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/klauspost/compress v1.15.15 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/magiconair/properties v1.8.6 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mitchellh/pointerstructure v1.2.0 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect @@ -106,12 +126,17 @@ require ( github.com/prometheus/common v0.39.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sanity-io/litter v1.5.1 // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/status-im/keycard-go v0.2.0 // indirect github.com/subosito/gotenv v1.3.0 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/zondax/hid v0.9.1 // indirect github.com/zondax/ledger-go v0.14.1 // indirect diff --git a/go.sum b/go.sum index 09e5526b3f20..c027a0a85867 100644 --- a/go.sum +++ b/go.sum @@ -52,12 +52,18 @@ github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cq github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= +github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY= +github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/ava-labs/coreth v0.12.7-0.20231026130315-648dfa6abecd h1:Kgh+NpQ5VaiQpX8NJ32HqbYPVqA8vo3zG3v7JKLFs1A= +github.com/ava-labs/coreth v0.12.7-0.20231026130315-648dfa6abecd/go.mod h1:EsxxCWSBxMMZtgd62AS5ZtmGujZEFPp2EFq4JJCcJ8k= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 h1:EdxD90j5sClfL5Ngpz2TlnbnkNYdFPDXa0jDOjam65c= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7/go.mod h1:XhiXSrh90sHUbkERzaxEftCmUz53eCijshDLZ4fByVM= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= @@ -94,13 +100,18 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -130,12 +141,16 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= +github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= @@ -146,6 +161,14 @@ github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6ps github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= +github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= +github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= +github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -162,6 +185,8 @@ github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2 github.com/ethereum/go-ethereum v1.12.0/go.mod h1:/oo2X/dZLJjf2mJ6YT9wcWxa4nNJDBKDBU6sFIpx1Gs= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -170,6 +195,8 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= @@ -193,7 +220,11 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= @@ -278,10 +309,14 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -302,11 +337,17 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 h1:kr3j8iIMR4ywO/O0rvksXaJvauGGCMg2zAZIiNZ9uIQ= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0/go.mod h1:ummNFgdgLhhX7aIiy35vVmQNS0rWXknfPE0qe6fmFXg= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw= +github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e/go.mod h1:j9cQbcqHQujT0oKJ38PylVfqohClLr3CvDC+Qcg+lhU= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8= @@ -318,6 +359,7 @@ github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3 github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -359,6 +401,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -366,6 +409,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= @@ -376,11 +420,17 @@ github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -389,8 +439,11 @@ github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -409,6 +462,8 @@ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -476,6 +531,8 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sanity-io/litter v1.5.1 h1:dwnrSypP6q56o3lFxTU+t2fwQ9A+U5qrXVO4Qg9KwVU= github.com/sanity-io/litter v1.5.1/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0= @@ -511,6 +568,8 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= +github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -540,10 +599,14 @@ github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITn github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= +github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -555,6 +618,8 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1: github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= @@ -564,6 +629,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= @@ -661,6 +727,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -706,6 +773,7 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -729,6 +797,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -793,8 +862,12 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -811,6 +884,7 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -874,6 +948,7 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -998,6 +1073,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= diff --git a/node/node.go b/node/node.go index 9e72b7dcc450..4200a33699ab 100644 --- a/node/node.go +++ b/node/node.go @@ -24,7 +24,7 @@ import ( "go.uber.org/zap" - // coreth "github.com/ava-labs/coreth/plugin/evm" + coreth "github.com/ava-labs/coreth/plugin/evm" "github.com/ava-labs/avalanchego/api/admin" "github.com/ava-labs/avalanchego/api/auth" @@ -935,7 +935,7 @@ func (n *Node) initVMs() error { CreateAssetTxFee: n.Config.CreateAssetTxFee, }, }), - // vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), + vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), n.VMManager.RegisterFactory(context.TODO(), secp256k1fx.ID, &secp256k1fx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), nftfx.ID, &nftfx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), propertyfx.ID, &propertyfx.Factory{}), diff --git a/tests/e2e/c/dynamic_fees.go b/tests/e2e/c/dynamic_fees.go index 4234c170af6f..f3a1daaf3d2c 100644 --- a/tests/e2e/c/dynamic_fees.go +++ b/tests/e2e/c/dynamic_fees.go @@ -3,167 +3,167 @@ package c -// import ( -// "math/big" -// "strings" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/stretchr/testify/require" - -// "github.com/ethereum/go-ethereum/accounts/abi" -// "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/coreth/core/types" -// "github.com/ava-labs/coreth/params" -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/tests" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/tests/fixture/testnet" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// ) - -// // This test uses the compiled bin for `hashing.sol` as -// // well as its ABI contained in `hashing_contract.go`. - -// var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { -// require := require.New(ginkgo.GinkgoT()) - -// // Need a gas limit much larger than the standard 21_000 to enable -// // the contract to induce a gas price increase -// const largeGasLimit = uint64(8_000_000) - -// // TODO(marun) What is the significance of this value? -// gasTip := big.NewInt(1000 * params.GWei) - -// ginkgo.It("should ensure that the gas price is affected by load", func() { -// ginkgo.By("creating a new private network to ensure isolation from other tests") -// privateNetwork := e2e.Env.NewPrivateNetwork() - -// ginkgo.By("allocating a pre-funded key") -// key := privateNetwork.GetConfig().FundedKeys[0] -// ethAddress := evm.GetEthAddress(key) - -// ginkgo.By("initializing a coreth client") -// node := privateNetwork.GetNodes()[0] -// nodeURI := testnet.NodeURI{ -// NodeID: node.GetID(), -// URI: node.GetProcessContext().URI, -// } -// ethClient := e2e.Env.NewEthClient(nodeURI) - -// ginkgo.By("initializing a transaction signer") -// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) -// require.NoError(err) -// signer := types.NewEIP155Signer(cChainID) -// ecdsaKey := key.ToECDSA() -// sign := func(tx *types.Transaction) *types.Transaction { -// signedTx, err := types.SignTx(tx, signer, ecdsaKey) -// require.NoError(err) -// return signedTx -// } - -// var contractAddress common.Address -// ginkgo.By("deploying an expensive contract", func() { -// // Create transaction -// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) -// require.NoError(err) -// compiledContract := common.Hex2Bytes(hashingCompiledContract) -// tx := types.NewTx(&types.LegacyTx{ -// Nonce: nonce, -// GasPrice: gasTip, -// Gas: largeGasLimit, -// Value: common.Big0, -// Data: compiledContract, -// }) - -// // Send the transaction and wait for acceptance -// signedTx := sign(tx) -// receipt := e2e.SendEthTransaction(ethClient, signedTx) - -// contractAddress = receipt.ContractAddress -// }) - -// var gasPrice *big.Int -// ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { -// // Evaluate the bytes representation of the contract -// hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) -// require.NoError(err) -// contractData, err := hashingABI.Pack("hashIt") -// require.NoError(err) - -// var initialGasPrice *big.Int -// e2e.Eventually(func() bool { -// // Check the gas price -// var err error -// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) -// require.NoError(err) -// if initialGasPrice == nil { -// initialGasPrice = gasPrice -// tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) -// } else if gasPrice.Cmp(initialGasPrice) > 0 { -// // Gas price has increased -// tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) -// return true -// } - -// // Create the transaction -// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) -// require.NoError(err) -// tx := types.NewTx(&types.LegacyTx{ -// Nonce: nonce, -// GasPrice: gasTip, -// Gas: largeGasLimit, -// To: &contractAddress, -// Value: common.Big0, -// Data: contractData, -// }) - -// // Send the transaction and wait for acceptance -// signedTx := sign(tx) -// _ = e2e.SendEthTransaction(ethClient, signedTx) - -// // The gas price will be checked at the start of the next iteration -// return false -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") -// }) - -// ginkgo.By("waiting for the gas price to decrease...", func() { -// initialGasPrice := gasPrice -// e2e.Eventually(func() bool { -// var err error -// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) -// require.NoError(err) -// tests.Outf("{{blue}}.{{/}}") -// return initialGasPrice.Cmp(gasPrice) > 0 -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") -// tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) -// }) - -// ginkgo.By("sending funds at the current gas price", func() { -// // Create a recipient address -// factory := secp256k1.Factory{} -// recipientKey, err := factory.NewPrivateKey() -// require.NoError(err) -// recipientEthAddress := evm.GetEthAddress(recipientKey) - -// // Create transaction -// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) -// require.NoError(err) -// tx := types.NewTx(&types.LegacyTx{ -// Nonce: nonce, -// GasPrice: gasPrice, -// Gas: e2e.DefaultGasLimit, -// To: &recipientEthAddress, -// Value: common.Big0, -// }) - -// // Send the transaction and wait for acceptance -// signedTx := sign(tx) -// _ = e2e.SendEthTransaction(ethClient, signedTx) -// }) - -// e2e.CheckBootstrapIsPossible(privateNetwork) -// }) -// }) +import ( + "math/big" + "strings" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/coreth/params" + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/tests" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/tests/fixture/testnet" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +) + +// This test uses the compiled bin for `hashing.sol` as +// well as its ABI contained in `hashing_contract.go`. + +var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { + require := require.New(ginkgo.GinkgoT()) + + // Need a gas limit much larger than the standard 21_000 to enable + // the contract to induce a gas price increase + const largeGasLimit = uint64(8_000_000) + + // TODO(marun) What is the significance of this value? + gasTip := big.NewInt(1000 * params.GWei) + + ginkgo.It("should ensure that the gas price is affected by load", func() { + ginkgo.By("creating a new private network to ensure isolation from other tests") + privateNetwork := e2e.Env.NewPrivateNetwork() + + ginkgo.By("allocating a pre-funded key") + key := privateNetwork.GetConfig().FundedKeys[0] + ethAddress := evm.GetEthAddress(key) + + ginkgo.By("initializing a coreth client") + node := privateNetwork.GetNodes()[0] + nodeURI := testnet.NodeURI{ + NodeID: node.GetID(), + URI: node.GetProcessContext().URI, + } + ethClient := e2e.Env.NewEthClient(nodeURI) + + ginkgo.By("initializing a transaction signer") + cChainID, err := ethClient.ChainID(e2e.DefaultContext()) + require.NoError(err) + signer := types.NewEIP155Signer(cChainID) + ecdsaKey := key.ToECDSA() + sign := func(tx *types.Transaction) *types.Transaction { + signedTx, err := types.SignTx(tx, signer, ecdsaKey) + require.NoError(err) + return signedTx + } + + var contractAddress common.Address + ginkgo.By("deploying an expensive contract", func() { + // Create transaction + nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) + require.NoError(err) + compiledContract := common.Hex2Bytes(hashingCompiledContract) + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + GasPrice: gasTip, + Gas: largeGasLimit, + Value: common.Big0, + Data: compiledContract, + }) + + // Send the transaction and wait for acceptance + signedTx := sign(tx) + receipt := e2e.SendEthTransaction(ethClient, signedTx) + + contractAddress = receipt.ContractAddress + }) + + var gasPrice *big.Int + ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { + // Evaluate the bytes representation of the contract + hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) + require.NoError(err) + contractData, err := hashingABI.Pack("hashIt") + require.NoError(err) + + var initialGasPrice *big.Int + e2e.Eventually(func() bool { + // Check the gas price + var err error + gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) + require.NoError(err) + if initialGasPrice == nil { + initialGasPrice = gasPrice + tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) + } else if gasPrice.Cmp(initialGasPrice) > 0 { + // Gas price has increased + tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) + return true + } + + // Create the transaction + nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) + require.NoError(err) + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + GasPrice: gasTip, + Gas: largeGasLimit, + To: &contractAddress, + Value: common.Big0, + Data: contractData, + }) + + // Send the transaction and wait for acceptance + signedTx := sign(tx) + _ = e2e.SendEthTransaction(ethClient, signedTx) + + // The gas price will be checked at the start of the next iteration + return false + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") + }) + + ginkgo.By("waiting for the gas price to decrease...", func() { + initialGasPrice := gasPrice + e2e.Eventually(func() bool { + var err error + gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) + require.NoError(err) + tests.Outf("{{blue}}.{{/}}") + return initialGasPrice.Cmp(gasPrice) > 0 + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") + tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) + }) + + ginkgo.By("sending funds at the current gas price", func() { + // Create a recipient address + factory := secp256k1.Factory{} + recipientKey, err := factory.NewPrivateKey() + require.NoError(err) + recipientEthAddress := evm.GetEthAddress(recipientKey) + + // Create transaction + nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) + require.NoError(err) + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + GasPrice: gasPrice, + Gas: e2e.DefaultGasLimit, + To: &recipientEthAddress, + Value: common.Big0, + }) + + // Send the transaction and wait for acceptance + signedTx := sign(tx) + _ = e2e.SendEthTransaction(ethClient, signedTx) + }) + + e2e.CheckBootstrapIsPossible(privateNetwork) + }) +}) diff --git a/tests/e2e/c/interchain_workflow.go b/tests/e2e/c/interchain_workflow.go index a072596e1dc9..47c430d4c12a 100644 --- a/tests/e2e/c/interchain_workflow.go +++ b/tests/e2e/c/interchain_workflow.go @@ -3,164 +3,164 @@ package c -// import ( -// "math/big" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/stretchr/testify/require" - -// "github.com/ava-labs/coreth/core/types" -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { -// require := require.New(ginkgo.GinkgoT()) - -// const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer - -// ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { -// ginkgo.By("initializing a new eth client") -// // Select a random node URI to use for both the eth client and -// // the wallet to avoid having to verify that all nodes are at -// // the same height before initializing the wallet. -// nodeURI := e2e.Env.GetRandomNodeURI() -// ethClient := e2e.Env.NewEthClient(nodeURI) - -// ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") -// senderKey := e2e.Env.AllocateFundedKey() -// senderEthAddress := evm.GetEthAddress(senderKey) -// factory := secp256k1.Factory{} -// recipientKey, err := factory.NewPrivateKey() -// require.NoError(err) -// recipientEthAddress := evm.GetEthAddress(recipientKey) - -// ginkgo.By("sending funds from one address to another on the C-Chain", func() { -// // Create transaction -// acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) -// require.NoError(err) -// gasPrice := e2e.SuggestGasPrice(ethClient) -// tx := types.NewTransaction( -// acceptedNonce, -// recipientEthAddress, -// big.NewInt(int64(txAmount)), -// e2e.DefaultGasLimit, -// gasPrice, -// nil, -// ) - -// // Sign transaction -// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) -// require.NoError(err) -// signer := types.NewEIP155Signer(cChainID) -// signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) -// require.NoError(err) - -// _ = e2e.SendEthTransaction(ethClient, signedTx) - -// ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") -// e2e.Eventually(func() bool { -// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) -// require.NoError(err) -// return balance.Cmp(big.NewInt(0)) > 0 -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") -// }) - -// // Wallet must be initialized after sending funds on the -// // C-Chain with the same node URI to ensure wallet state -// // matches on-chain state. -// ginkgo.By("initializing a keychain and associated wallet") -// keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) -// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) -// xWallet := baseWallet.X() -// cWallet := baseWallet.C() -// pWallet := baseWallet.P() - -// ginkgo.By("defining common configuration") -// avaxAssetID := xWallet.AVAXAssetID() -// // Use the same owner for import funds to X-Chain and P-Chain -// recipientOwner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// recipientKey.Address(), -// }, -// } -// // Use the same outputs for both X-Chain and P-Chain exports -// exportOutputs := []*secp256k1fx.TransferOutput{ -// { -// Amt: txAmount, -// OutputOwners: secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// keychain.Keys[0].Address(), -// }, -// }, -// }, -// } - -// ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { -// _, err := cWallet.IssueExportTx( -// xWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { -// _, err := xWallet.IssueImportTx( -// cWallet.BlockchainID(), -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { -// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { -// _, err := cWallet.IssueExportTx( -// constants.PlatformChainID, -// exportOutputs, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { -// _, err = pWallet.IssueImportTx( -// cWallet.BlockchainID(), -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { -// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) -// }) -// }) +import ( + "math/big" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { + require := require.New(ginkgo.GinkgoT()) + + const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer + + ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { + ginkgo.By("initializing a new eth client") + // Select a random node URI to use for both the eth client and + // the wallet to avoid having to verify that all nodes are at + // the same height before initializing the wallet. + nodeURI := e2e.Env.GetRandomNodeURI() + ethClient := e2e.Env.NewEthClient(nodeURI) + + ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") + senderKey := e2e.Env.AllocateFundedKey() + senderEthAddress := evm.GetEthAddress(senderKey) + factory := secp256k1.Factory{} + recipientKey, err := factory.NewPrivateKey() + require.NoError(err) + recipientEthAddress := evm.GetEthAddress(recipientKey) + + ginkgo.By("sending funds from one address to another on the C-Chain", func() { + // Create transaction + acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) + require.NoError(err) + gasPrice := e2e.SuggestGasPrice(ethClient) + tx := types.NewTransaction( + acceptedNonce, + recipientEthAddress, + big.NewInt(int64(txAmount)), + e2e.DefaultGasLimit, + gasPrice, + nil, + ) + + // Sign transaction + cChainID, err := ethClient.ChainID(e2e.DefaultContext()) + require.NoError(err) + signer := types.NewEIP155Signer(cChainID) + signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) + require.NoError(err) + + _ = e2e.SendEthTransaction(ethClient, signedTx) + + ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") + e2e.Eventually(func() bool { + balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) + require.NoError(err) + return balance.Cmp(big.NewInt(0)) > 0 + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") + }) + + // Wallet must be initialized after sending funds on the + // C-Chain with the same node URI to ensure wallet state + // matches on-chain state. + ginkgo.By("initializing a keychain and associated wallet") + keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) + baseWallet := e2e.Env.NewWallet(keychain, nodeURI) + xWallet := baseWallet.X() + cWallet := baseWallet.C() + pWallet := baseWallet.P() + + ginkgo.By("defining common configuration") + avaxAssetID := xWallet.AVAXAssetID() + // Use the same owner for import funds to X-Chain and P-Chain + recipientOwner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + recipientKey.Address(), + }, + } + // Use the same outputs for both X-Chain and P-Chain exports + exportOutputs := []*secp256k1fx.TransferOutput{ + { + Amt: txAmount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + keychain.Keys[0].Address(), + }, + }, + }, + } + + ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { + _, err := cWallet.IssueExportTx( + xWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { + _, err := xWallet.IssueImportTx( + cWallet.BlockchainID(), + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { + balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { + _, err := cWallet.IssueExportTx( + constants.PlatformChainID, + exportOutputs, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { + _, err = pWallet.IssueImportTx( + cWallet.BlockchainID(), + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { + balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) + }) +}) diff --git a/tests/e2e/e2e.go b/tests/e2e/e2e.go index c124d50adb3b..130f33f1197c 100644 --- a/tests/e2e/e2e.go +++ b/tests/e2e/e2e.go @@ -7,24 +7,22 @@ package e2e import ( "context" "encoding/json" - - // "errors" - // "fmt" - // "math/big" + "errors" + "fmt" + "math/big" "math/rand" "os" "path/filepath" - - // "strings" + "strings" "time" ginkgo "github.com/onsi/ginkgo/v2" "github.com/stretchr/testify/require" - // "github.com/ava-labs/coreth/core/types" - // "github.com/ava-labs/coreth/ethclient" - // "github.com/ava-labs/coreth/interfaces" + "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/coreth/ethclient" + "github.com/ava-labs/coreth/interfaces" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/tests" @@ -136,7 +134,7 @@ func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain, nodeURI tes baseWallet, err := primary.MakeWallet(DefaultContext(), &primary.WalletConfig{ URI: nodeURI.URI, AVAXKeychain: keychain, - // EthKeychain: keychain, + EthKeychain: keychain, }) te.require.NoError(err) return primary.NewWalletWithOptions( @@ -149,16 +147,16 @@ func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain, nodeURI tes ) } -// // Create a new eth client targeting the specified node URI. -// // TODO(marun) Make this a regular function. -// func (te *TestEnvironment) NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { -// tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) -// nodeAddress := strings.Split(nodeURI.URI, "//")[1] -// uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) -// client, err := ethclient.Dial(uri) -// te.require.NoError(err) -// return client -// } +// Create a new eth client targeting the specified node URI. +// TODO(marun) Make this a regular function. +func (te *TestEnvironment) NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { + tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) + nodeAddress := strings.Split(nodeURI.URI, "//")[1] + uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) + client, err := ethclient.Dial(uri) + te.require.NoError(err) + return client +} // Create a new private network that is not shared with other tests. func (te *TestEnvironment) NewPrivateNetwork() testnet.Network { @@ -233,49 +231,49 @@ func WaitForHealthy(node testnet.Node) { require.NoError(ginkgo.GinkgoT(), testnet.WaitForHealthy(DefaultContext(), node)) } -// // Sends an eth transaction, waits for the transaction receipt to be issued -// // and checks that the receipt indicates success. -// func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { -// require := require.New(ginkgo.GinkgoT()) - -// txID := signedTx.Hash() -// tests.Outf(" sending eth transaction with ID: %s\n", txID) - -// require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) - -// // Wait for the receipt -// var receipt *types.Receipt -// Eventually(func() bool { -// var err error -// receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) -// if errors.Is(err, interfaces.NotFound) { -// return false // Transaction is still pending -// } -// require.NoError(err) -// return true -// }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") - -// require.Equal(receipt.Status, types.ReceiptStatusSuccessful) -// return receipt -// } - -// // Determines the suggested gas price for the configured client that will -// // maximize the chances of transaction acceptance. -// func SuggestGasPrice(ethClient ethclient.Client) *big.Int { -// gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) -// require.NoError(ginkgo.GinkgoT(), err) -// // Double the suggested gas price to maximize the chances of -// // acceptance. Maybe this can be revisited pending resolution of -// // https://github.com/ava-labs/coreth/issues/314. -// gasPrice.Add(gasPrice, gasPrice) -// return gasPrice -// } - -// // Helper simplifying use via an option of a gas price appropriate for testing. -// func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { -// baseFee := SuggestGasPrice(ethClient) -// return common.WithBaseFee(baseFee) -// } +// Sends an eth transaction, waits for the transaction receipt to be issued +// and checks that the receipt indicates success. +func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { + require := require.New(ginkgo.GinkgoT()) + + txID := signedTx.Hash() + tests.Outf(" sending eth transaction with ID: %s\n", txID) + + require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) + + // Wait for the receipt + var receipt *types.Receipt + Eventually(func() bool { + var err error + receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) + if errors.Is(err, interfaces.NotFound) { + return false // Transaction is still pending + } + require.NoError(err) + return true + }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") + + require.Equal(receipt.Status, types.ReceiptStatusSuccessful) + return receipt +} + +// Determines the suggested gas price for the configured client that will +// maximize the chances of transaction acceptance. +func SuggestGasPrice(ethClient ethclient.Client) *big.Int { + gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) + require.NoError(ginkgo.GinkgoT(), err) + // Double the suggested gas price to maximize the chances of + // acceptance. Maybe this can be revisited pending resolution of + // https://github.com/ava-labs/coreth/issues/314. + gasPrice.Add(gasPrice, gasPrice) + return gasPrice +} + +// Helper simplifying use via an option of a gas price appropriate for testing. +func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { + baseFee := SuggestGasPrice(ethClient) + return common.WithBaseFee(baseFee) +} // Verify that a new node can bootstrap into the network. func CheckBootstrapIsPossible(network testnet.Network) { diff --git a/tests/e2e/p/interchain_workflow.go b/tests/e2e/p/interchain_workflow.go index c5bc47517967..10c15fd002a7 100644 --- a/tests/e2e/p/interchain_workflow.go +++ b/tests/e2e/p/interchain_workflow.go @@ -3,226 +3,226 @@ package p -// import ( -// "math/big" -// "time" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/spf13/cast" - -// "github.com/stretchr/testify/require" - -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/api/info" -// "github.com/ava-labs/avalanchego/config" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/tests/fixture/testnet" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/platformvm/reward" -// "github.com/ava-labs/avalanchego/vms/platformvm/txs" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { -// require := require.New(ginkgo.GinkgoT()) - -// const ( -// transferAmount = 10 * units.Avax -// weight = 2_000 * units.Avax // Used for both validation and delegation -// ) - -// ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { -// network := e2e.Env.GetNetwork() - -// ginkgo.By("checking that the network has a compatible minimum stake duration", func() { -// minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) -// require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) -// }) - -// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") -// factory := secp256k1.Factory{} -// recipientKey, err := factory.NewPrivateKey() -// require.NoError(err) -// keychain := e2e.Env.NewKeychain(1) -// keychain.Add(recipientKey) -// nodeURI := e2e.Env.GetRandomNodeURI() -// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) -// xWallet := baseWallet.X() -// cWallet := baseWallet.C() -// pWallet := baseWallet.P() - -// ginkgo.By("defining common configuration") -// recipientEthAddress := evm.GetEthAddress(recipientKey) -// avaxAssetID := xWallet.AVAXAssetID() -// // Use the same owner for sending to X-Chain and importing funds to P-Chain -// recipientOwner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// recipientKey.Address(), -// }, -// } -// // Use the same outputs for both X-Chain and C-Chain exports -// exportOutputs := []*avax.TransferableOutput{ -// { -// Asset: avax.Asset{ -// ID: avaxAssetID, -// }, -// Out: &secp256k1fx.TransferOutput{ -// Amt: transferAmount, -// OutputOwners: secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// keychain.Keys[0].Address(), -// }, -// }, -// }, -// }, -// } - -// ginkgo.By("adding new node and waiting for it to report healthy") -// node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) -// e2e.WaitForHealthy(node) - -// ginkgo.By("retrieving new node's id and pop") -// infoClient := info.NewClient(node.GetProcessContext().URI) -// nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) -// require.NoError(err) - -// ginkgo.By("adding the new node as a validator", func() { -// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) -// // Validation duration doesn't actually matter to this -// // test - it is only ensuring that adding a validator -// // doesn't break interchain transfer. -// endTime := startTime.Add(30 * time.Second) - -// rewardKey, err := factory.NewPrivateKey() -// require.NoError(err) - -// const ( -// delegationPercent = 0.10 // 10% -// delegationShare = reward.PercentDenominator * delegationPercent -// ) - -// _, err = pWallet.IssueAddPermissionlessValidatorTx( -// &txs.SubnetValidator{ -// Validator: txs.Validator{ -// NodeID: nodeID, -// Start: uint64(startTime.Unix()), -// End: uint64(endTime.Unix()), -// Wght: weight, -// }, -// Subnet: constants.PrimaryNetworkID, -// }, -// nodePOP, -// pWallet.AVAXAssetID(), -// &secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{rewardKey.Address()}, -// }, -// &secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{rewardKey.Address()}, -// }, -// delegationShare, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("adding a delegator to the new node", func() { -// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) -// // Delegation duration doesn't actually matter to this -// // test - it is only ensuring that adding a delegator -// // doesn't break interchain transfer. -// endTime := startTime.Add(15 * time.Second) - -// rewardKey, err := factory.NewPrivateKey() -// require.NoError(err) - -// _, err = pWallet.IssueAddPermissionlessDelegatorTx( -// &txs.SubnetValidator{ -// Validator: txs.Validator{ -// NodeID: nodeID, -// Start: uint64(startTime.Unix()), -// End: uint64(endTime.Unix()), -// Wght: weight, -// }, -// Subnet: constants.PrimaryNetworkID, -// }, -// pWallet.AVAXAssetID(), -// &secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{rewardKey.Address()}, -// }, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { -// _, err := pWallet.IssueExportTx( -// xWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { -// _, err := xWallet.IssueImportTx( -// constants.PlatformChainID, -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { -// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { -// _, err := pWallet.IssueExportTx( -// cWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("initializing a new eth client") -// ethClient := e2e.Env.NewEthClient(nodeURI) - -// ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { -// _, err := cWallet.IssueImportTx( -// constants.PlatformChainID, -// recipientEthAddress, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") -// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) -// require.NoError(err) -// require.Positive(balance.Cmp(big.NewInt(0))) - -// ginkgo.By("stopping validator node to free up resources for a bootstrap check") -// require.NoError(node.Stop()) - -// e2e.CheckBootstrapIsPossible(network) -// }) -// }) +import ( + "math/big" + "time" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/spf13/cast" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/api/info" + "github.com/ava-labs/avalanchego/config" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/tests/fixture/testnet" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/platformvm/reward" + "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { + require := require.New(ginkgo.GinkgoT()) + + const ( + transferAmount = 10 * units.Avax + weight = 2_000 * units.Avax // Used for both validation and delegation + ) + + ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { + network := e2e.Env.GetNetwork() + + ginkgo.By("checking that the network has a compatible minimum stake duration", func() { + minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) + require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) + }) + + ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") + factory := secp256k1.Factory{} + recipientKey, err := factory.NewPrivateKey() + require.NoError(err) + keychain := e2e.Env.NewKeychain(1) + keychain.Add(recipientKey) + nodeURI := e2e.Env.GetRandomNodeURI() + baseWallet := e2e.Env.NewWallet(keychain, nodeURI) + xWallet := baseWallet.X() + cWallet := baseWallet.C() + pWallet := baseWallet.P() + + ginkgo.By("defining common configuration") + recipientEthAddress := evm.GetEthAddress(recipientKey) + avaxAssetID := xWallet.AVAXAssetID() + // Use the same owner for sending to X-Chain and importing funds to P-Chain + recipientOwner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + recipientKey.Address(), + }, + } + // Use the same outputs for both X-Chain and C-Chain exports + exportOutputs := []*avax.TransferableOutput{ + { + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: transferAmount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + keychain.Keys[0].Address(), + }, + }, + }, + }, + } + + ginkgo.By("adding new node and waiting for it to report healthy") + node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) + e2e.WaitForHealthy(node) + + ginkgo.By("retrieving new node's id and pop") + infoClient := info.NewClient(node.GetProcessContext().URI) + nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) + require.NoError(err) + + ginkgo.By("adding the new node as a validator", func() { + startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) + // Validation duration doesn't actually matter to this + // test - it is only ensuring that adding a validator + // doesn't break interchain transfer. + endTime := startTime.Add(30 * time.Second) + + rewardKey, err := factory.NewPrivateKey() + require.NoError(err) + + const ( + delegationPercent = 0.10 // 10% + delegationShare = reward.PercentDenominator * delegationPercent + ) + + _, err = pWallet.IssueAddPermissionlessValidatorTx( + &txs.SubnetValidator{ + Validator: txs.Validator{ + NodeID: nodeID, + Start: uint64(startTime.Unix()), + End: uint64(endTime.Unix()), + Wght: weight, + }, + Subnet: constants.PrimaryNetworkID, + }, + nodePOP, + pWallet.AVAXAssetID(), + &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{rewardKey.Address()}, + }, + &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{rewardKey.Address()}, + }, + delegationShare, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("adding a delegator to the new node", func() { + startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) + // Delegation duration doesn't actually matter to this + // test - it is only ensuring that adding a delegator + // doesn't break interchain transfer. + endTime := startTime.Add(15 * time.Second) + + rewardKey, err := factory.NewPrivateKey() + require.NoError(err) + + _, err = pWallet.IssueAddPermissionlessDelegatorTx( + &txs.SubnetValidator{ + Validator: txs.Validator{ + NodeID: nodeID, + Start: uint64(startTime.Unix()), + End: uint64(endTime.Unix()), + Wght: weight, + }, + Subnet: constants.PrimaryNetworkID, + }, + pWallet.AVAXAssetID(), + &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{rewardKey.Address()}, + }, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { + _, err := pWallet.IssueExportTx( + xWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { + _, err := xWallet.IssueImportTx( + constants.PlatformChainID, + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { + balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { + _, err := pWallet.IssueExportTx( + cWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("initializing a new eth client") + ethClient := e2e.Env.NewEthClient(nodeURI) + + ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { + _, err := cWallet.IssueImportTx( + constants.PlatformChainID, + recipientEthAddress, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") + balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) + require.NoError(err) + require.Positive(balance.Cmp(big.NewInt(0))) + + ginkgo.By("stopping validator node to free up resources for a bootstrap check") + require.NoError(node.Stop()) + + e2e.CheckBootstrapIsPossible(network) + }) +}) diff --git a/tests/e2e/x/interchain_workflow.go b/tests/e2e/x/interchain_workflow.go index 5443e1a54ad4..550689ff60c9 100644 --- a/tests/e2e/x/interchain_workflow.go +++ b/tests/e2e/x/interchain_workflow.go @@ -3,152 +3,152 @@ package x -// import ( -// "math/big" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/stretchr/testify/require" - -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { -// require := require.New(ginkgo.GinkgoT()) - -// const transferAmount = 10 * units.Avax - -// ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { -// nodeURI := e2e.Env.GetRandomNodeURI() - -// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") -// factory := secp256k1.Factory{} -// recipientKey, err := factory.NewPrivateKey() -// require.NoError(err) -// keychain := e2e.Env.NewKeychain(1) -// keychain.Add(recipientKey) -// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) -// xWallet := baseWallet.X() -// cWallet := baseWallet.C() -// pWallet := baseWallet.P() - -// ginkgo.By("defining common configuration") -// recipientEthAddress := evm.GetEthAddress(recipientKey) -// avaxAssetID := xWallet.AVAXAssetID() -// // Use the same owner for sending to X-Chain and importing funds to P-Chain -// recipientOwner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// recipientKey.Address(), -// }, -// } -// // Use the same outputs for both C-Chain and P-Chain exports -// exportOutputs := []*avax.TransferableOutput{ -// { -// Asset: avax.Asset{ -// ID: avaxAssetID, -// }, -// Out: &secp256k1fx.TransferOutput{ -// Amt: transferAmount, -// OutputOwners: secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// keychain.Keys[0].Address(), -// }, -// }, -// }, -// }, -// } - -// ginkgo.By("sending funds from one address to another on the X-Chain", func() { -// _, err = xWallet.IssueBaseTx( -// []*avax.TransferableOutput{{ -// Asset: avax.Asset{ -// ID: avaxAssetID, -// }, -// Out: &secp256k1fx.TransferOutput{ -// Amt: transferAmount, -// OutputOwners: recipientOwner, -// }, -// }}, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { -// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { -// _, err := xWallet.IssueExportTx( -// cWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("initializing a new eth client") -// ethClient := e2e.Env.NewEthClient(nodeURI) - -// ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { -// _, err := cWallet.IssueImportTx( -// xWallet.BlockchainID(), -// recipientEthAddress, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") -// e2e.Eventually(func() bool { -// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) -// require.NoError(err) -// return balance.Cmp(big.NewInt(0)) > 0 -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") - -// ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { -// _, err := xWallet.IssueExportTx( -// constants.PlatformChainID, -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { -// _, err := pWallet.IssueImportTx( -// xWallet.BlockchainID(), -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { -// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) -// }) -// }) +import ( + "math/big" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { + require := require.New(ginkgo.GinkgoT()) + + const transferAmount = 10 * units.Avax + + ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { + nodeURI := e2e.Env.GetRandomNodeURI() + + ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") + factory := secp256k1.Factory{} + recipientKey, err := factory.NewPrivateKey() + require.NoError(err) + keychain := e2e.Env.NewKeychain(1) + keychain.Add(recipientKey) + baseWallet := e2e.Env.NewWallet(keychain, nodeURI) + xWallet := baseWallet.X() + cWallet := baseWallet.C() + pWallet := baseWallet.P() + + ginkgo.By("defining common configuration") + recipientEthAddress := evm.GetEthAddress(recipientKey) + avaxAssetID := xWallet.AVAXAssetID() + // Use the same owner for sending to X-Chain and importing funds to P-Chain + recipientOwner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + recipientKey.Address(), + }, + } + // Use the same outputs for both C-Chain and P-Chain exports + exportOutputs := []*avax.TransferableOutput{ + { + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: transferAmount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + keychain.Keys[0].Address(), + }, + }, + }, + }, + } + + ginkgo.By("sending funds from one address to another on the X-Chain", func() { + _, err = xWallet.IssueBaseTx( + []*avax.TransferableOutput{{ + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: transferAmount, + OutputOwners: recipientOwner, + }, + }}, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { + balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { + _, err := xWallet.IssueExportTx( + cWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("initializing a new eth client") + ethClient := e2e.Env.NewEthClient(nodeURI) + + ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { + _, err := cWallet.IssueImportTx( + xWallet.BlockchainID(), + recipientEthAddress, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") + e2e.Eventually(func() bool { + balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) + require.NoError(err) + return balance.Cmp(big.NewInt(0)) > 0 + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") + + ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { + _, err := xWallet.IssueExportTx( + constants.PlatformChainID, + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { + _, err := pWallet.IssueImportTx( + xWallet.BlockchainID(), + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { + balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) + }) +}) diff --git a/tests/fixture/testnet/config.go b/tests/fixture/testnet/config.go index 80a795b3d5e2..10d51104eef4 100644 --- a/tests/fixture/testnet/config.go +++ b/tests/fixture/testnet/config.go @@ -15,9 +15,9 @@ import ( "github.com/spf13/cast" - // "github.com/ava-labs/coreth/core" - // "github.com/ava-labs/coreth/params" - // "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/coreth/core" + "github.com/ava-labs/coreth/params" + "github.com/ava-labs/coreth/plugin/evm" "github.com/ava-labs/avalanchego/config" "github.com/ava-labs/avalanchego/genesis" @@ -143,15 +143,15 @@ func (c *NetworkConfig) EnsureGenesis(networkID uint32, validatorIDs []ids.NodeI // Ensure pre-funded keys have arbitrary large balances on both chains to support testing xChainBalances := make(XChainBalanceMap, len(c.FundedKeys)) - // cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) - // for _, key := range c.FundedKeys { - // xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount - // cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ - // Balance: DefaultFundedKeyCChainAmount, - // } - // } - - genesis, err := NewTestGenesis(networkID, xChainBalances /*cChainBalances,*/, validatorIDs) + cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) + for _, key := range c.FundedKeys { + xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount + cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ + Balance: DefaultFundedKeyCChainAmount, + } + } + + genesis, err := NewTestGenesis(networkID, xChainBalances, cChainBalances, validatorIDs) if err != nil { return err } @@ -311,7 +311,7 @@ type XChainBalanceMap map[ids.ShortID]uint64 func NewTestGenesis( networkID uint32, xChainBalances XChainBalanceMap, - // cChainBalances core.GenesisAlloc, + cChainBalances core.GenesisAlloc, validatorIDs []ids.NodeID, ) (*genesis.UnparsedConfig, error) { // Validate inputs @@ -322,7 +322,7 @@ func NewTestGenesis( if len(validatorIDs) == 0 { return nil, errMissingValidatorsForGenesis } - if len(xChainBalances) == 0 /*|| len(cChainBalances) == 0*/ { + if len(xChainBalances) == 0 || len(cChainBalances) == 0 { return nil, errMissingBalancesForGenesis } @@ -394,20 +394,20 @@ func NewTestGenesis( ) } - // // Define C-Chain genesis - // cChainGenesis := &core.Genesis{ - // Config: ¶ms.ChainConfig{ - // ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary - // }, - // Difficulty: big.NewInt(0), // Difficulty is a mandatory field - // GasLimit: DefaultGasLimit, - // Alloc: cChainBalances, - // } - // cChainGenesisBytes, err := json.Marshal(cChainGenesis) - // if err != nil { - // return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) - // } - // config.CChainGenesis = string(cChainGenesisBytes) + // Define C-Chain genesis + cChainGenesis := &core.Genesis{ + Config: ¶ms.ChainConfig{ + ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary + }, + Difficulty: big.NewInt(0), // Difficulty is a mandatory field + GasLimit: DefaultGasLimit, + Alloc: cChainBalances, + } + cChainGenesisBytes, err := json.Marshal(cChainGenesis) + if err != nil { + return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) + } + config.CChainGenesis = string(cChainGenesisBytes) // Give staking rewards for initial validators to a random address. Any testing of staking rewards // will be easier to perform with nodes other than the initial validators since the timing of diff --git a/vms/example/xsvm/cmd/chain/create/cmd.go b/vms/example/xsvm/cmd/chain/create/cmd.go index 043b4298dcdf..1f00491a4ce6 100644 --- a/vms/example/xsvm/cmd/chain/create/cmd.go +++ b/vms/example/xsvm/cmd/chain/create/cmd.go @@ -42,9 +42,9 @@ func createFunc(c *cobra.Command, args []string) error { // that [uri] is hosting. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: config.URI, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: config.URI, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(config.SubnetID), }) if err != nil { diff --git a/wallet/chain/c/backend.go b/wallet/chain/c/backend.go index b88c8c643bc3..0a735116b646 100644 --- a/wallet/chain/c/backend.go +++ b/wallet/chain/c/backend.go @@ -3,153 +3,153 @@ package c -// import ( -// "errors" -// "fmt" -// "math/big" -// "sync" - -// stdcontext "context" - -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/database" -// "github.com/ava-labs/avalanchego/utils/math" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var ( -// _ Backend = (*backend)(nil) - -// errUnknownTxType = errors.New("unknown tx type") -// ) - -// // Backend defines the full interface required to support a C-chain wallet. -// type Backend interface { -// common.ChainUTXOs -// BuilderBackend -// SignerBackend - -// AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error -// } - -// type backend struct { -// Context -// common.ChainUTXOs - -// accountsLock sync.RWMutex -// accounts map[ethcommon.Address]*Account -// } - -// type Account struct { -// Balance *big.Int -// Nonce uint64 -// } - -// func NewBackend( -// ctx Context, -// utxos common.ChainUTXOs, -// accounts map[ethcommon.Address]*Account, -// ) Backend { -// return &backend{ -// Context: ctx, -// ChainUTXOs: utxos, -// accounts: accounts, -// } -// } - -// func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { -// switch tx := tx.UnsignedAtomicTx.(type) { -// case *evm.UnsignedImportTx: -// for _, input := range tx.ImportedInputs { -// utxoID := input.InputID() -// if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { -// return err -// } -// } - -// b.accountsLock.Lock() -// defer b.accountsLock.Unlock() - -// for _, output := range tx.Outs { -// account, ok := b.accounts[output.Address] -// if !ok { -// continue -// } - -// balance := new(big.Int).SetUint64(output.Amount) -// balance.Mul(balance, avaxConversionRate) -// account.Balance.Add(account.Balance, balance) -// } -// case *evm.UnsignedExportTx: -// txID := tx.ID() -// for i, out := range tx.ExportedOutputs { -// err := b.AddUTXO( -// ctx, -// tx.DestinationChain, -// &avax.UTXO{ -// UTXOID: avax.UTXOID{ -// TxID: txID, -// OutputIndex: uint32(i), -// }, -// Asset: avax.Asset{ID: out.AssetID()}, -// Out: out.Out, -// }, -// ) -// if err != nil { -// return err -// } -// } - -// b.accountsLock.Lock() -// defer b.accountsLock.Unlock() - -// for _, input := range tx.Ins { -// account, ok := b.accounts[input.Address] -// if !ok { -// continue -// } - -// balance := new(big.Int).SetUint64(input.Amount) -// balance.Mul(balance, avaxConversionRate) -// if account.Balance.Cmp(balance) == -1 { -// return errInsufficientFunds -// } -// account.Balance.Sub(account.Balance, balance) - -// newNonce, err := math.Add64(input.Nonce, 1) -// if err != nil { -// return err -// } -// account.Nonce = newNonce -// } -// default: -// return fmt.Errorf("%w: %T", errUnknownTxType, tx) -// } -// return nil -// } - -// func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { -// b.accountsLock.RLock() -// defer b.accountsLock.RUnlock() - -// account, exists := b.accounts[addr] -// if !exists { -// return nil, database.ErrNotFound -// } -// return account.Balance, nil -// } - -// func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { -// b.accountsLock.RLock() -// defer b.accountsLock.RUnlock() - -// account, exists := b.accounts[addr] -// if !exists { -// return 0, database.ErrNotFound -// } -// return account.Nonce, nil -// } +import ( + "errors" + "fmt" + "math/big" + "sync" + + stdcontext "context" + + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/utils/math" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var ( + _ Backend = (*backend)(nil) + + errUnknownTxType = errors.New("unknown tx type") +) + +// Backend defines the full interface required to support a C-chain wallet. +type Backend interface { + common.ChainUTXOs + BuilderBackend + SignerBackend + + AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error +} + +type backend struct { + Context + common.ChainUTXOs + + accountsLock sync.RWMutex + accounts map[ethcommon.Address]*Account +} + +type Account struct { + Balance *big.Int + Nonce uint64 +} + +func NewBackend( + ctx Context, + utxos common.ChainUTXOs, + accounts map[ethcommon.Address]*Account, +) Backend { + return &backend{ + Context: ctx, + ChainUTXOs: utxos, + accounts: accounts, + } +} + +func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { + switch tx := tx.UnsignedAtomicTx.(type) { + case *evm.UnsignedImportTx: + for _, input := range tx.ImportedInputs { + utxoID := input.InputID() + if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { + return err + } + } + + b.accountsLock.Lock() + defer b.accountsLock.Unlock() + + for _, output := range tx.Outs { + account, ok := b.accounts[output.Address] + if !ok { + continue + } + + balance := new(big.Int).SetUint64(output.Amount) + balance.Mul(balance, avaxConversionRate) + account.Balance.Add(account.Balance, balance) + } + case *evm.UnsignedExportTx: + txID := tx.ID() + for i, out := range tx.ExportedOutputs { + err := b.AddUTXO( + ctx, + tx.DestinationChain, + &avax.UTXO{ + UTXOID: avax.UTXOID{ + TxID: txID, + OutputIndex: uint32(i), + }, + Asset: avax.Asset{ID: out.AssetID()}, + Out: out.Out, + }, + ) + if err != nil { + return err + } + } + + b.accountsLock.Lock() + defer b.accountsLock.Unlock() + + for _, input := range tx.Ins { + account, ok := b.accounts[input.Address] + if !ok { + continue + } + + balance := new(big.Int).SetUint64(input.Amount) + balance.Mul(balance, avaxConversionRate) + if account.Balance.Cmp(balance) == -1 { + return errInsufficientFunds + } + account.Balance.Sub(account.Balance, balance) + + newNonce, err := math.Add64(input.Nonce, 1) + if err != nil { + return err + } + account.Nonce = newNonce + } + default: + return fmt.Errorf("%w: %T", errUnknownTxType, tx) + } + return nil +} + +func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { + b.accountsLock.RLock() + defer b.accountsLock.RUnlock() + + account, exists := b.accounts[addr] + if !exists { + return nil, database.ErrNotFound + } + return account.Balance, nil +} + +func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { + b.accountsLock.RLock() + defer b.accountsLock.RUnlock() + + account, exists := b.accounts[addr] + if !exists { + return 0, database.ErrNotFound + } + return account.Nonce, nil +} diff --git a/wallet/chain/c/builder.go b/wallet/chain/c/builder.go index c51d2647777e..d2d088e88a53 100644 --- a/wallet/chain/c/builder.go +++ b/wallet/chain/c/builder.go @@ -3,399 +3,399 @@ package c -// import ( -// "errors" -// "math/big" - -// stdcontext "context" - -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils" -// "github.com/ava-labs/avalanchego/utils/math" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// const avaxConversionRateInt = 1_000_000_000 - -// var ( -// _ Builder = (*builder)(nil) - -// errInsufficientFunds = errors.New("insufficient funds") - -// // avaxConversionRate is the conversion rate between the smallest -// // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest -// // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. -// // -// // This is only required for AVAX because the denomination of 1 AVAX is 9 -// // decimal places on the X and P chains, but is 18 decimal places within the -// // EVM. -// avaxConversionRate = big.NewInt(avaxConversionRateInt) -// ) - -// // Builder provides a convenient interface for building unsigned C-chain -// // transactions. -// type Builder interface { -// // GetBalance calculates the amount of AVAX that this builder has control -// // over. -// GetBalance( -// options ...common.Option, -// ) (*big.Int, error) - -// // GetImportableBalance calculates the amount of AVAX that this builder -// // could import from the provided chain. -// // -// // - [chainID] specifies the chain the funds are from. -// GetImportableBalance( -// chainID ids.ID, -// options ...common.Option, -// ) (uint64, error) - -// // NewImportTx creates an import transaction that attempts to consume all -// // the available UTXOs and import the funds to [to]. -// // -// // - [chainID] specifies the chain to be importing funds from. -// // - [to] specifies where to send the imported funds to. -// // - [baseFee] specifies the fee price willing to be paid by this tx. -// NewImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedImportTx, error) - -// // NewExportTx creates an export transaction that attempts to send all the -// // provided [outputs] to the requested [chainID]. -// // -// // - [chainID] specifies the chain to be exporting the funds to. -// // - [outputs] specifies the outputs to send to the [chainID]. -// // - [baseFee] specifies the fee price willing to be paid by this tx. -// NewExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedExportTx, error) -// } - -// // BuilderBackend specifies the required information needed to build unsigned -// // C-chain transactions. -// type BuilderBackend interface { -// Context - -// UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) -// Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) -// Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) -// } - -// type builder struct { -// avaxAddrs set.Set[ids.ShortID] -// ethAddrs set.Set[ethcommon.Address] -// backend BuilderBackend -// } - -// // NewBuilder returns a new transaction builder. -// // -// // - [avaxAddrs] is the set of addresses in the AVAX format that the builder -// // assumes can be used when signing the transactions in the future. -// // - [ethAddrs] is the set of addresses in the Eth format that the builder -// // assumes can be used when signing the transactions in the future. -// // - [backend] provides the required access to the chain's context and state -// // to build out the transactions. -// func NewBuilder( -// avaxAddrs set.Set[ids.ShortID], -// ethAddrs set.Set[ethcommon.Address], -// backend BuilderBackend, -// ) Builder { -// return &builder{ -// avaxAddrs: avaxAddrs, -// ethAddrs: ethAddrs, -// backend: backend, -// } -// } - -// func (b *builder) GetBalance( -// options ...common.Option, -// ) (*big.Int, error) { -// var ( -// ops = common.NewOptions(options) -// ctx = ops.Context() -// addrs = ops.EthAddresses(b.ethAddrs) -// totalBalance = new(big.Int) -// ) -// for addr := range addrs { -// balance, err := b.backend.Balance(ctx, addr) -// if err != nil { -// return nil, err -// } -// totalBalance.Add(totalBalance, balance) -// } - -// return totalBalance, nil -// } - -// func (b *builder) GetImportableBalance( -// chainID ids.ID, -// options ...common.Option, -// ) (uint64, error) { -// ops := common.NewOptions(options) -// utxos, err := b.backend.UTXOs(ops.Context(), chainID) -// if err != nil { -// return 0, err -// } - -// var ( -// addrs = ops.Addresses(b.avaxAddrs) -// minIssuanceTime = ops.MinIssuanceTime() -// avaxAssetID = b.backend.AVAXAssetID() -// balance uint64 -// ) -// for _, utxo := range utxos { -// amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) -// if !ok { -// continue -// } - -// newBalance, err := math.Add64(balance, amount) -// if err != nil { -// return 0, err -// } -// balance = newBalance -// } - -// return balance, nil -// } - -// func (b *builder) NewImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedImportTx, error) { -// ops := common.NewOptions(options) -// utxos, err := b.backend.UTXOs(ops.Context(), chainID) -// if err != nil { -// return nil, err -// } - -// var ( -// addrs = ops.Addresses(b.avaxAddrs) -// minIssuanceTime = ops.MinIssuanceTime() -// avaxAssetID = b.backend.AVAXAssetID() - -// importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) -// importedAmount uint64 -// ) -// for _, utxo := range utxos { -// amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) -// if !ok { -// continue -// } - -// importedInputs = append(importedInputs, &avax.TransferableInput{ -// UTXOID: utxo.UTXOID, -// Asset: utxo.Asset, -// In: &secp256k1fx.TransferInput{ -// Amt: amount, -// Input: secp256k1fx.Input{ -// SigIndices: inputSigIndices, -// }, -// }, -// }) - -// newImportedAmount, err := math.Add64(importedAmount, amount) -// if err != nil { -// return nil, err -// } -// importedAmount = newImportedAmount -// } - -// utils.Sort(importedInputs) -// tx := &evm.UnsignedImportTx{ -// NetworkID: b.backend.NetworkID(), -// BlockchainID: b.backend.BlockchainID(), -// SourceChain: chainID, -// ImportedInputs: importedInputs, -// } - -// // We must initialize the bytes of the tx to calculate the initial cost -// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} -// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { -// return nil, err -// } - -// gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) -// if err != nil { -// return nil, err -// } -// gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas - -// txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) -// if err != nil { -// return nil, err -// } - -// if importedAmount <= txFee { -// return nil, errInsufficientFunds -// } - -// tx.Outs = []evm.EVMOutput{{ -// Address: to, -// Amount: importedAmount - txFee, -// AssetID: avaxAssetID, -// }} -// return tx, nil -// } - -// func (b *builder) NewExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedExportTx, error) { -// var ( -// avaxAssetID = b.backend.AVAXAssetID() -// exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) -// exportedAmount uint64 -// ) -// for i, output := range outputs { -// exportedOutputs[i] = &avax.TransferableOutput{ -// Asset: avax.Asset{ID: avaxAssetID}, -// Out: output, -// } - -// newExportedAmount, err := math.Add64(exportedAmount, output.Amt) -// if err != nil { -// return nil, err -// } -// exportedAmount = newExportedAmount -// } - -// avax.SortTransferableOutputs(exportedOutputs, evm.Codec) -// tx := &evm.UnsignedExportTx{ -// NetworkID: b.backend.NetworkID(), -// BlockchainID: b.backend.BlockchainID(), -// DestinationChain: chainID, -// ExportedOutputs: exportedOutputs, -// } - -// // We must initialize the bytes of the tx to calculate the initial cost -// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} -// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { -// return nil, err -// } - -// cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) -// if err != nil { -// return nil, err -// } - -// initialFee, err := evm.CalculateDynamicFee(cost, baseFee) -// if err != nil { -// return nil, err -// } - -// amountToConsume, err := math.Add64(exportedAmount, initialFee) -// if err != nil { -// return nil, err -// } - -// var ( -// ops = common.NewOptions(options) -// ctx = ops.Context() -// addrs = ops.EthAddresses(b.ethAddrs) -// inputs = make([]evm.EVMInput, 0, addrs.Len()) -// ) -// for addr := range addrs { -// if amountToConsume == 0 { -// break -// } - -// prevFee, err := evm.CalculateDynamicFee(cost, baseFee) -// if err != nil { -// return nil, err -// } - -// newCost := cost + evm.EVMInputGas -// newFee, err := evm.CalculateDynamicFee(newCost, baseFee) -// if err != nil { -// return nil, err -// } - -// additionalFee := newFee - prevFee - -// balance, err := b.backend.Balance(ctx, addr) -// if err != nil { -// return nil, err -// } - -// // Since the asset is AVAX, we divide by the avaxConversionRate to -// // convert back to the correct denomination of AVAX that can be -// // exported. -// avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() - -// // If the balance for [addr] is insufficient to cover the additional -// // cost of adding an input to the transaction, skip adding the input -// // altogether. -// if avaxBalance <= additionalFee { -// continue -// } - -// // Update the cost for the next iteration -// cost = newCost - -// amountToConsume, err = math.Add64(amountToConsume, additionalFee) -// if err != nil { -// return nil, err -// } - -// nonce, err := b.backend.Nonce(ctx, addr) -// if err != nil { -// return nil, err -// } - -// inputAmount := math.Min(amountToConsume, avaxBalance) -// inputs = append(inputs, evm.EVMInput{ -// Address: addr, -// Amount: inputAmount, -// AssetID: avaxAssetID, -// Nonce: nonce, -// }) -// amountToConsume -= inputAmount -// } - -// if amountToConsume > 0 { -// return nil, errInsufficientFunds -// } - -// utils.Sort(inputs) -// tx.Ins = inputs -// return tx, nil -// } - -// func getSpendableAmount( -// utxo *avax.UTXO, -// addrs set.Set[ids.ShortID], -// minIssuanceTime uint64, -// avaxAssetID ids.ID, -// ) (uint64, []uint32, bool) { -// if utxo.Asset.ID != avaxAssetID { -// // Only AVAX can be imported -// return 0, nil, false -// } - -// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) -// if !ok { -// // Can't import an unknown transfer output type -// return 0, nil, false -// } - -// inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) -// return out.Amt, inputSigIndices, ok -// } +import ( + "errors" + "math/big" + + stdcontext "context" + + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils" + "github.com/ava-labs/avalanchego/utils/math" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +const avaxConversionRateInt = 1_000_000_000 + +var ( + _ Builder = (*builder)(nil) + + errInsufficientFunds = errors.New("insufficient funds") + + // avaxConversionRate is the conversion rate between the smallest + // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest + // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. + // + // This is only required for AVAX because the denomination of 1 AVAX is 9 + // decimal places on the X and P chains, but is 18 decimal places within the + // EVM. + avaxConversionRate = big.NewInt(avaxConversionRateInt) +) + +// Builder provides a convenient interface for building unsigned C-chain +// transactions. +type Builder interface { + // GetBalance calculates the amount of AVAX that this builder has control + // over. + GetBalance( + options ...common.Option, + ) (*big.Int, error) + + // GetImportableBalance calculates the amount of AVAX that this builder + // could import from the provided chain. + // + // - [chainID] specifies the chain the funds are from. + GetImportableBalance( + chainID ids.ID, + options ...common.Option, + ) (uint64, error) + + // NewImportTx creates an import transaction that attempts to consume all + // the available UTXOs and import the funds to [to]. + // + // - [chainID] specifies the chain to be importing funds from. + // - [to] specifies where to send the imported funds to. + // - [baseFee] specifies the fee price willing to be paid by this tx. + NewImportTx( + chainID ids.ID, + to ethcommon.Address, + baseFee *big.Int, + options ...common.Option, + ) (*evm.UnsignedImportTx, error) + + // NewExportTx creates an export transaction that attempts to send all the + // provided [outputs] to the requested [chainID]. + // + // - [chainID] specifies the chain to be exporting the funds to. + // - [outputs] specifies the outputs to send to the [chainID]. + // - [baseFee] specifies the fee price willing to be paid by this tx. + NewExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + baseFee *big.Int, + options ...common.Option, + ) (*evm.UnsignedExportTx, error) +} + +// BuilderBackend specifies the required information needed to build unsigned +// C-chain transactions. +type BuilderBackend interface { + Context + + UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) + Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) + Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) +} + +type builder struct { + avaxAddrs set.Set[ids.ShortID] + ethAddrs set.Set[ethcommon.Address] + backend BuilderBackend +} + +// NewBuilder returns a new transaction builder. +// +// - [avaxAddrs] is the set of addresses in the AVAX format that the builder +// assumes can be used when signing the transactions in the future. +// - [ethAddrs] is the set of addresses in the Eth format that the builder +// assumes can be used when signing the transactions in the future. +// - [backend] provides the required access to the chain's context and state +// to build out the transactions. +func NewBuilder( + avaxAddrs set.Set[ids.ShortID], + ethAddrs set.Set[ethcommon.Address], + backend BuilderBackend, +) Builder { + return &builder{ + avaxAddrs: avaxAddrs, + ethAddrs: ethAddrs, + backend: backend, + } +} + +func (b *builder) GetBalance( + options ...common.Option, +) (*big.Int, error) { + var ( + ops = common.NewOptions(options) + ctx = ops.Context() + addrs = ops.EthAddresses(b.ethAddrs) + totalBalance = new(big.Int) + ) + for addr := range addrs { + balance, err := b.backend.Balance(ctx, addr) + if err != nil { + return nil, err + } + totalBalance.Add(totalBalance, balance) + } + + return totalBalance, nil +} + +func (b *builder) GetImportableBalance( + chainID ids.ID, + options ...common.Option, +) (uint64, error) { + ops := common.NewOptions(options) + utxos, err := b.backend.UTXOs(ops.Context(), chainID) + if err != nil { + return 0, err + } + + var ( + addrs = ops.Addresses(b.avaxAddrs) + minIssuanceTime = ops.MinIssuanceTime() + avaxAssetID = b.backend.AVAXAssetID() + balance uint64 + ) + for _, utxo := range utxos { + amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) + if !ok { + continue + } + + newBalance, err := math.Add64(balance, amount) + if err != nil { + return 0, err + } + balance = newBalance + } + + return balance, nil +} + +func (b *builder) NewImportTx( + chainID ids.ID, + to ethcommon.Address, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedImportTx, error) { + ops := common.NewOptions(options) + utxos, err := b.backend.UTXOs(ops.Context(), chainID) + if err != nil { + return nil, err + } + + var ( + addrs = ops.Addresses(b.avaxAddrs) + minIssuanceTime = ops.MinIssuanceTime() + avaxAssetID = b.backend.AVAXAssetID() + + importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) + importedAmount uint64 + ) + for _, utxo := range utxos { + amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) + if !ok { + continue + } + + importedInputs = append(importedInputs, &avax.TransferableInput{ + UTXOID: utxo.UTXOID, + Asset: utxo.Asset, + In: &secp256k1fx.TransferInput{ + Amt: amount, + Input: secp256k1fx.Input{ + SigIndices: inputSigIndices, + }, + }, + }) + + newImportedAmount, err := math.Add64(importedAmount, amount) + if err != nil { + return nil, err + } + importedAmount = newImportedAmount + } + + utils.Sort(importedInputs) + tx := &evm.UnsignedImportTx{ + NetworkID: b.backend.NetworkID(), + BlockchainID: b.backend.BlockchainID(), + SourceChain: chainID, + ImportedInputs: importedInputs, + } + + // We must initialize the bytes of the tx to calculate the initial cost + wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} + if err := wrappedTx.Sign(evm.Codec, nil); err != nil { + return nil, err + } + + gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) + if err != nil { + return nil, err + } + gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas + + txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) + if err != nil { + return nil, err + } + + if importedAmount <= txFee { + return nil, errInsufficientFunds + } + + tx.Outs = []evm.EVMOutput{{ + Address: to, + Amount: importedAmount - txFee, + AssetID: avaxAssetID, + }} + return tx, nil +} + +func (b *builder) NewExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedExportTx, error) { + var ( + avaxAssetID = b.backend.AVAXAssetID() + exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) + exportedAmount uint64 + ) + for i, output := range outputs { + exportedOutputs[i] = &avax.TransferableOutput{ + Asset: avax.Asset{ID: avaxAssetID}, + Out: output, + } + + newExportedAmount, err := math.Add64(exportedAmount, output.Amt) + if err != nil { + return nil, err + } + exportedAmount = newExportedAmount + } + + avax.SortTransferableOutputs(exportedOutputs, evm.Codec) + tx := &evm.UnsignedExportTx{ + NetworkID: b.backend.NetworkID(), + BlockchainID: b.backend.BlockchainID(), + DestinationChain: chainID, + ExportedOutputs: exportedOutputs, + } + + // We must initialize the bytes of the tx to calculate the initial cost + wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} + if err := wrappedTx.Sign(evm.Codec, nil); err != nil { + return nil, err + } + + cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) + if err != nil { + return nil, err + } + + initialFee, err := evm.CalculateDynamicFee(cost, baseFee) + if err != nil { + return nil, err + } + + amountToConsume, err := math.Add64(exportedAmount, initialFee) + if err != nil { + return nil, err + } + + var ( + ops = common.NewOptions(options) + ctx = ops.Context() + addrs = ops.EthAddresses(b.ethAddrs) + inputs = make([]evm.EVMInput, 0, addrs.Len()) + ) + for addr := range addrs { + if amountToConsume == 0 { + break + } + + prevFee, err := evm.CalculateDynamicFee(cost, baseFee) + if err != nil { + return nil, err + } + + newCost := cost + evm.EVMInputGas + newFee, err := evm.CalculateDynamicFee(newCost, baseFee) + if err != nil { + return nil, err + } + + additionalFee := newFee - prevFee + + balance, err := b.backend.Balance(ctx, addr) + if err != nil { + return nil, err + } + + // Since the asset is AVAX, we divide by the avaxConversionRate to + // convert back to the correct denomination of AVAX that can be + // exported. + avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() + + // If the balance for [addr] is insufficient to cover the additional + // cost of adding an input to the transaction, skip adding the input + // altogether. + if avaxBalance <= additionalFee { + continue + } + + // Update the cost for the next iteration + cost = newCost + + amountToConsume, err = math.Add64(amountToConsume, additionalFee) + if err != nil { + return nil, err + } + + nonce, err := b.backend.Nonce(ctx, addr) + if err != nil { + return nil, err + } + + inputAmount := math.Min(amountToConsume, avaxBalance) + inputs = append(inputs, evm.EVMInput{ + Address: addr, + Amount: inputAmount, + AssetID: avaxAssetID, + Nonce: nonce, + }) + amountToConsume -= inputAmount + } + + if amountToConsume > 0 { + return nil, errInsufficientFunds + } + + utils.Sort(inputs) + tx.Ins = inputs + return tx, nil +} + +func getSpendableAmount( + utxo *avax.UTXO, + addrs set.Set[ids.ShortID], + minIssuanceTime uint64, + avaxAssetID ids.ID, +) (uint64, []uint32, bool) { + if utxo.Asset.ID != avaxAssetID { + // Only AVAX can be imported + return 0, nil, false + } + + out, ok := utxo.Out.(*secp256k1fx.TransferOutput) + if !ok { + // Can't import an unknown transfer output type + return 0, nil, false + } + + inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) + return out.Amt, inputSigIndices, ok +} diff --git a/wallet/chain/c/builder_with_options.go b/wallet/chain/c/builder_with_options.go index 9b7ab8399484..8416dddf9928 100644 --- a/wallet/chain/c/builder_with_options.go +++ b/wallet/chain/c/builder_with_options.go @@ -3,81 +3,81 @@ package c -// import ( -// "math/big" +import ( + "math/big" -// "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/coreth/plugin/evm" -// ethcommon "github.com/ethereum/go-ethereum/common" + ethcommon "github.com/ethereum/go-ethereum/common" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) -// var _ Builder = (*builderWithOptions)(nil) +var _ Builder = (*builderWithOptions)(nil) -// type builderWithOptions struct { -// Builder -// options []common.Option -// } +type builderWithOptions struct { + Builder + options []common.Option +} -// // NewBuilderWithOptions returns a new transaction builder that will use the -// // given options by default. -// // -// // - [builder] is the builder that will be called to perform the underlying -// // operations. -// // - [options] will be provided to the builder in addition to the options -// // provided in the method calls. -// func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { -// return &builderWithOptions{ -// Builder: builder, -// options: options, -// } -// } +// NewBuilderWithOptions returns a new transaction builder that will use the +// given options by default. +// +// - [builder] is the builder that will be called to perform the underlying +// operations. +// - [options] will be provided to the builder in addition to the options +// provided in the method calls. +func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { + return &builderWithOptions{ + Builder: builder, + options: options, + } +} -// func (b *builderWithOptions) GetBalance( -// options ...common.Option, -// ) (*big.Int, error) { -// return b.Builder.GetBalance( -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) GetBalance( + options ...common.Option, +) (*big.Int, error) { + return b.Builder.GetBalance( + common.UnionOptions(b.options, options)..., + ) +} -// func (b *builderWithOptions) GetImportableBalance( -// chainID ids.ID, -// options ...common.Option, -// ) (uint64, error) { -// return b.Builder.GetImportableBalance( -// chainID, -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) GetImportableBalance( + chainID ids.ID, + options ...common.Option, +) (uint64, error) { + return b.Builder.GetImportableBalance( + chainID, + common.UnionOptions(b.options, options)..., + ) +} -// func (b *builderWithOptions) NewImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedImportTx, error) { -// return b.Builder.NewImportTx( -// chainID, -// to, -// baseFee, -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) NewImportTx( + chainID ids.ID, + to ethcommon.Address, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedImportTx, error) { + return b.Builder.NewImportTx( + chainID, + to, + baseFee, + common.UnionOptions(b.options, options)..., + ) +} -// func (b *builderWithOptions) NewExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedExportTx, error) { -// return b.Builder.NewExportTx( -// chainID, -// outputs, -// baseFee, -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) NewExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedExportTx, error) { + return b.Builder.NewExportTx( + chainID, + outputs, + baseFee, + common.UnionOptions(b.options, options)..., + ) +} diff --git a/wallet/chain/c/context.go b/wallet/chain/c/context.go index 1c01d8fb55c8..d506b42f81fa 100644 --- a/wallet/chain/c/context.go +++ b/wallet/chain/c/context.go @@ -3,81 +3,81 @@ package c -// import ( -// stdcontext "context" +import ( + stdcontext "context" -// "github.com/ava-labs/avalanchego/api/info" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/avm" -// ) + "github.com/ava-labs/avalanchego/api/info" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/avm" +) -// var _ Context = (*context)(nil) +var _ Context = (*context)(nil) -// type Context interface { -// NetworkID() uint32 -// BlockchainID() ids.ID -// AVAXAssetID() ids.ID -// } +type Context interface { + NetworkID() uint32 + BlockchainID() ids.ID + AVAXAssetID() ids.ID +} -// type context struct { -// networkID uint32 -// blockchainID ids.ID -// avaxAssetID ids.ID -// } +type context struct { + networkID uint32 + blockchainID ids.ID + avaxAssetID ids.ID +} -// func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { -// infoClient := info.NewClient(uri) -// xChainClient := avm.NewClient(uri, "X") -// return NewContextFromClients(ctx, infoClient, xChainClient) -// } +func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { + infoClient := info.NewClient(uri) + xChainClient := avm.NewClient(uri, "X") + return NewContextFromClients(ctx, infoClient, xChainClient) +} -// func NewContextFromClients( -// ctx stdcontext.Context, -// infoClient info.Client, -// xChainClient avm.Client, -// ) (Context, error) { -// networkID, err := infoClient.GetNetworkID(ctx) -// if err != nil { -// return nil, err -// } +func NewContextFromClients( + ctx stdcontext.Context, + infoClient info.Client, + xChainClient avm.Client, +) (Context, error) { + networkID, err := infoClient.GetNetworkID(ctx) + if err != nil { + return nil, err + } -// chainID, err := infoClient.GetBlockchainID(ctx, "C") -// if err != nil { -// return nil, err -// } + chainID, err := infoClient.GetBlockchainID(ctx, "C") + if err != nil { + return nil, err + } -// asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") -// if err != nil { -// return nil, err -// } + asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") + if err != nil { + return nil, err + } -// return NewContext( -// networkID, -// chainID, -// asset.AssetID, -// ), nil -// } + return NewContext( + networkID, + chainID, + asset.AssetID, + ), nil +} -// func NewContext( -// networkID uint32, -// blockchainID ids.ID, -// avaxAssetID ids.ID, -// ) Context { -// return &context{ -// networkID: networkID, -// blockchainID: blockchainID, -// avaxAssetID: avaxAssetID, -// } -// } +func NewContext( + networkID uint32, + blockchainID ids.ID, + avaxAssetID ids.ID, +) Context { + return &context{ + networkID: networkID, + blockchainID: blockchainID, + avaxAssetID: avaxAssetID, + } +} -// func (c *context) NetworkID() uint32 { -// return c.networkID -// } +func (c *context) NetworkID() uint32 { + return c.networkID +} -// func (c *context) BlockchainID() ids.ID { -// return c.blockchainID -// } +func (c *context) BlockchainID() ids.ID { + return c.blockchainID +} -// func (c *context) AVAXAssetID() ids.ID { -// return c.avaxAssetID -// } +func (c *context) AVAXAssetID() ids.ID { + return c.avaxAssetID +} diff --git a/wallet/chain/c/signer.go b/wallet/chain/c/signer.go index 4bedc378234b..4fd85ed3b532 100644 --- a/wallet/chain/c/signer.go +++ b/wallet/chain/c/signer.go @@ -3,221 +3,221 @@ package c -// import ( -// "errors" -// "fmt" - -// stdcontext "context" - -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/database" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils/crypto/keychain" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/hashing" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/components/verify" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// ) - -// const version = 0 - -// var ( -// _ Signer = (*txSigner)(nil) - -// errUnknownInputType = errors.New("unknown input type") -// errUnknownCredentialType = errors.New("unknown credential type") -// errUnknownOutputType = errors.New("unknown output type") -// errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") - -// emptySig [secp256k1.SignatureLen]byte -// ) - -// type Signer interface { -// SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) -// SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error -// } - -// type EthKeychain interface { -// // The returned Signer can provide a signature for [addr] -// GetEth(addr ethcommon.Address) (keychain.Signer, bool) -// // Returns the set of addresses for which the accessor keeps an associated -// // signer -// EthAddresses() set.Set[ethcommon.Address] -// } - -// type SignerBackend interface { -// GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) -// } - -// type txSigner struct { -// avaxKC keychain.Keychain -// ethKC EthKeychain -// backend SignerBackend -// } - -// func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { -// return &txSigner{ -// avaxKC: avaxKC, -// ethKC: ethKC, -// backend: backend, -// } -// } - -// func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { -// tx := &evm.Tx{UnsignedAtomicTx: utx} -// return tx, s.SignAtomic(ctx, tx) -// } - -// func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { -// switch utx := tx.UnsignedAtomicTx.(type) { -// case *evm.UnsignedImportTx: -// signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) -// if err != nil { -// return err -// } -// return sign(tx, true, signers) -// case *evm.UnsignedExportTx: -// signers := s.getExportSigners(utx.Ins) -// return sign(tx, true, signers) -// default: -// return fmt.Errorf("%w: %T", errUnknownTxType, tx) -// } -// } - -// func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { -// txSigners := make([][]keychain.Signer, len(ins)) -// for credIndex, transferInput := range ins { -// input, ok := transferInput.In.(*secp256k1fx.TransferInput) -// if !ok { -// return nil, errUnknownInputType -// } - -// inputSigners := make([]keychain.Signer, len(input.SigIndices)) -// txSigners[credIndex] = inputSigners - -// utxoID := transferInput.InputID() -// utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) -// if err == database.ErrNotFound { -// // If we don't have access to the UTXO, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// if err != nil { -// return nil, err -// } - -// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) -// if !ok { -// return nil, errUnknownOutputType -// } - -// for sigIndex, addrIndex := range input.SigIndices { -// if addrIndex >= uint32(len(out.Addrs)) { -// return nil, errInvalidUTXOSigIndex -// } - -// addr := out.Addrs[addrIndex] -// key, ok := s.avaxKC.Get(addr) -// if !ok { -// // If we don't have access to the key, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// inputSigners[sigIndex] = key -// } -// } -// return txSigners, nil -// } - -// func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { -// txSigners := make([][]keychain.Signer, len(ins)) -// for credIndex, input := range ins { -// inputSigners := make([]keychain.Signer, 1) -// txSigners[credIndex] = inputSigners - -// key, ok := s.ethKC.GetEth(input.Address) -// if !ok { -// // If we don't have access to the key, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// inputSigners[0] = key -// } -// return txSigners -// } - -// // TODO: remove [signHash] after the ledger supports signing all transactions. -// func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { -// unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) -// if err != nil { -// return fmt.Errorf("couldn't marshal unsigned tx: %w", err) -// } -// unsignedHash := hashing.ComputeHash256(unsignedBytes) - -// if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { -// tx.Creds = make([]verify.Verifiable, expectedLen) -// } - -// sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) -// for credIndex, inputSigners := range txSigners { -// credIntf := tx.Creds[credIndex] -// if credIntf == nil { -// credIntf = &secp256k1fx.Credential{} -// tx.Creds[credIndex] = credIntf -// } - -// cred, ok := credIntf.(*secp256k1fx.Credential) -// if !ok { -// return errUnknownCredentialType -// } -// if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { -// cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) -// } - -// for sigIndex, signer := range inputSigners { -// if signer == nil { -// // If we don't have access to the key, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// addr := signer.Address() -// if sig := cred.Sigs[sigIndex]; sig != emptySig { -// // If this signature has already been populated, we can just -// // copy the needed signature for the future. -// sigCache[addr] = sig -// continue -// } - -// if sig, exists := sigCache[addr]; exists { -// // If this key has already produced a signature, we can just -// // copy the previous signature. -// cred.Sigs[sigIndex] = sig -// continue -// } - -// var sig []byte -// if signHash { -// sig, err = signer.SignHash(unsignedHash) -// } else { -// sig, err = signer.Sign(unsignedBytes) -// } -// if err != nil { -// return fmt.Errorf("problem signing tx: %w", err) -// } -// copy(cred.Sigs[sigIndex][:], sig) -// sigCache[addr] = cred.Sigs[sigIndex] -// } -// } - -// signedBytes, err := evm.Codec.Marshal(version, tx) -// if err != nil { -// return fmt.Errorf("couldn't marshal tx: %w", err) -// } -// tx.Initialize(unsignedBytes, signedBytes) -// return nil -// } +import ( + "errors" + "fmt" + + stdcontext "context" + + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/crypto/keychain" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/hashing" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/components/verify" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" +) + +const version = 0 + +var ( + _ Signer = (*txSigner)(nil) + + errUnknownInputType = errors.New("unknown input type") + errUnknownCredentialType = errors.New("unknown credential type") + errUnknownOutputType = errors.New("unknown output type") + errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") + + emptySig [secp256k1.SignatureLen]byte +) + +type Signer interface { + SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) + SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error +} + +type EthKeychain interface { + // The returned Signer can provide a signature for [addr] + GetEth(addr ethcommon.Address) (keychain.Signer, bool) + // Returns the set of addresses for which the accessor keeps an associated + // signer + EthAddresses() set.Set[ethcommon.Address] +} + +type SignerBackend interface { + GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) +} + +type txSigner struct { + avaxKC keychain.Keychain + ethKC EthKeychain + backend SignerBackend +} + +func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { + return &txSigner{ + avaxKC: avaxKC, + ethKC: ethKC, + backend: backend, + } +} + +func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { + tx := &evm.Tx{UnsignedAtomicTx: utx} + return tx, s.SignAtomic(ctx, tx) +} + +func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { + switch utx := tx.UnsignedAtomicTx.(type) { + case *evm.UnsignedImportTx: + signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) + if err != nil { + return err + } + return sign(tx, true, signers) + case *evm.UnsignedExportTx: + signers := s.getExportSigners(utx.Ins) + return sign(tx, true, signers) + default: + return fmt.Errorf("%w: %T", errUnknownTxType, tx) + } +} + +func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { + txSigners := make([][]keychain.Signer, len(ins)) + for credIndex, transferInput := range ins { + input, ok := transferInput.In.(*secp256k1fx.TransferInput) + if !ok { + return nil, errUnknownInputType + } + + inputSigners := make([]keychain.Signer, len(input.SigIndices)) + txSigners[credIndex] = inputSigners + + utxoID := transferInput.InputID() + utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) + if err == database.ErrNotFound { + // If we don't have access to the UTXO, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + if err != nil { + return nil, err + } + + out, ok := utxo.Out.(*secp256k1fx.TransferOutput) + if !ok { + return nil, errUnknownOutputType + } + + for sigIndex, addrIndex := range input.SigIndices { + if addrIndex >= uint32(len(out.Addrs)) { + return nil, errInvalidUTXOSigIndex + } + + addr := out.Addrs[addrIndex] + key, ok := s.avaxKC.Get(addr) + if !ok { + // If we don't have access to the key, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + inputSigners[sigIndex] = key + } + } + return txSigners, nil +} + +func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { + txSigners := make([][]keychain.Signer, len(ins)) + for credIndex, input := range ins { + inputSigners := make([]keychain.Signer, 1) + txSigners[credIndex] = inputSigners + + key, ok := s.ethKC.GetEth(input.Address) + if !ok { + // If we don't have access to the key, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + inputSigners[0] = key + } + return txSigners +} + +// TODO: remove [signHash] after the ledger supports signing all transactions. +func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { + unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) + if err != nil { + return fmt.Errorf("couldn't marshal unsigned tx: %w", err) + } + unsignedHash := hashing.ComputeHash256(unsignedBytes) + + if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { + tx.Creds = make([]verify.Verifiable, expectedLen) + } + + sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) + for credIndex, inputSigners := range txSigners { + credIntf := tx.Creds[credIndex] + if credIntf == nil { + credIntf = &secp256k1fx.Credential{} + tx.Creds[credIndex] = credIntf + } + + cred, ok := credIntf.(*secp256k1fx.Credential) + if !ok { + return errUnknownCredentialType + } + if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { + cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) + } + + for sigIndex, signer := range inputSigners { + if signer == nil { + // If we don't have access to the key, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + addr := signer.Address() + if sig := cred.Sigs[sigIndex]; sig != emptySig { + // If this signature has already been populated, we can just + // copy the needed signature for the future. + sigCache[addr] = sig + continue + } + + if sig, exists := sigCache[addr]; exists { + // If this key has already produced a signature, we can just + // copy the previous signature. + cred.Sigs[sigIndex] = sig + continue + } + + var sig []byte + if signHash { + sig, err = signer.SignHash(unsignedHash) + } else { + sig, err = signer.Sign(unsignedBytes) + } + if err != nil { + return fmt.Errorf("problem signing tx: %w", err) + } + copy(cred.Sigs[sigIndex][:], sig) + sigCache[addr] = cred.Sigs[sigIndex] + } + } + + signedBytes, err := evm.Codec.Marshal(version, tx) + if err != nil { + return fmt.Errorf("couldn't marshal tx: %w", err) + } + tx.Initialize(unsignedBytes, signedBytes) + return nil +} diff --git a/wallet/chain/c/wallet.go b/wallet/chain/c/wallet.go index ebee50a9a958..fb1a83d53dad 100644 --- a/wallet/chain/c/wallet.go +++ b/wallet/chain/c/wallet.go @@ -3,204 +3,204 @@ package c -// import ( -// "errors" -// "math/big" -// "time" - -// "github.com/ava-labs/coreth/ethclient" -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var ( -// _ Wallet = (*wallet)(nil) - -// errNotCommitted = errors.New("not committed") -// ) - -// type Wallet interface { -// Context - -// // Builder returns the builder that will be used to create the transactions. -// Builder() Builder - -// // Signer returns the signer that will be used to sign the transactions. -// Signer() Signer - -// // IssueImportTx creates, signs, and issues an import transaction that -// // attempts to consume all the available UTXOs and import the funds to [to]. -// // -// // - [chainID] specifies the chain to be importing funds from. -// // - [to] specifies where to send the imported funds to. -// IssueImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// options ...common.Option, -// ) (*evm.Tx, error) - -// // IssueExportTx creates, signs, and issues an export transaction that -// // attempts to send all the provided [outputs] to the requested [chainID]. -// // -// // - [chainID] specifies the chain to be exporting the funds to. -// // - [outputs] specifies the outputs to send to the [chainID]. -// IssueExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// options ...common.Option, -// ) (*evm.Tx, error) - -// // IssueUnsignedTx signs and issues the unsigned tx. -// IssueUnsignedAtomicTx( -// utx evm.UnsignedAtomicTx, -// options ...common.Option, -// ) (*evm.Tx, error) - -// // IssueAtomicTx issues the signed tx. -// IssueAtomicTx( -// tx *evm.Tx, -// options ...common.Option, -// ) error -// } - -// func NewWallet( -// builder Builder, -// signer Signer, -// avaxClient evm.Client, -// ethClient ethclient.Client, -// backend Backend, -// ) Wallet { -// return &wallet{ -// Backend: backend, -// builder: builder, -// signer: signer, -// avaxClient: avaxClient, -// ethClient: ethClient, -// } -// } - -// type wallet struct { -// Backend -// builder Builder -// signer Signer -// avaxClient evm.Client -// ethClient ethclient.Client -// } - -// func (w *wallet) Builder() Builder { -// return w.builder -// } - -// func (w *wallet) Signer() Signer { -// return w.signer -// } - -// func (w *wallet) IssueImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// options ...common.Option, -// ) (*evm.Tx, error) { -// baseFee, err := w.baseFee(options) -// if err != nil { -// return nil, err -// } - -// utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) -// if err != nil { -// return nil, err -// } -// return w.IssueUnsignedAtomicTx(utx, options...) -// } - -// func (w *wallet) IssueExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// options ...common.Option, -// ) (*evm.Tx, error) { -// baseFee, err := w.baseFee(options) -// if err != nil { -// return nil, err -// } - -// utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) -// if err != nil { -// return nil, err -// } -// return w.IssueUnsignedAtomicTx(utx, options...) -// } - -// func (w *wallet) IssueUnsignedAtomicTx( -// utx evm.UnsignedAtomicTx, -// options ...common.Option, -// ) (*evm.Tx, error) { -// ops := common.NewOptions(options) -// ctx := ops.Context() -// tx, err := w.signer.SignUnsignedAtomic(ctx, utx) -// if err != nil { -// return nil, err -// } - -// return tx, w.IssueAtomicTx(tx, options...) -// } - -// func (w *wallet) IssueAtomicTx( -// tx *evm.Tx, -// options ...common.Option, -// ) error { -// ops := common.NewOptions(options) -// ctx := ops.Context() -// txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) -// if err != nil { -// return err -// } - -// if f := ops.PostIssuanceFunc(); f != nil { -// f(txID) -// } - -// if ops.AssumeDecided() { -// return w.Backend.AcceptAtomicTx(ctx, tx) -// } - -// pollFrequency := ops.PollFrequency() -// ticker := time.NewTicker(pollFrequency) -// defer ticker.Stop() - -// for { -// status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) -// if err != nil { -// return err -// } - -// switch status { -// case evm.Accepted: -// return w.Backend.AcceptAtomicTx(ctx, tx) -// case evm.Dropped, evm.Unknown: -// return errNotCommitted -// } - -// // The tx is Processing. - -// select { -// case <-ticker.C: -// case <-ctx.Done(): -// return ctx.Err() -// } -// } -// } - -// func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { -// ops := common.NewOptions(options) -// baseFee := ops.BaseFee(nil) -// if baseFee != nil { -// return baseFee, nil -// } - -// ctx := ops.Context() -// return w.ethClient.EstimateBaseFee(ctx) -// } +import ( + "errors" + "math/big" + "time" + + "github.com/ava-labs/coreth/ethclient" + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var ( + _ Wallet = (*wallet)(nil) + + errNotCommitted = errors.New("not committed") +) + +type Wallet interface { + Context + + // Builder returns the builder that will be used to create the transactions. + Builder() Builder + + // Signer returns the signer that will be used to sign the transactions. + Signer() Signer + + // IssueImportTx creates, signs, and issues an import transaction that + // attempts to consume all the available UTXOs and import the funds to [to]. + // + // - [chainID] specifies the chain to be importing funds from. + // - [to] specifies where to send the imported funds to. + IssueImportTx( + chainID ids.ID, + to ethcommon.Address, + options ...common.Option, + ) (*evm.Tx, error) + + // IssueExportTx creates, signs, and issues an export transaction that + // attempts to send all the provided [outputs] to the requested [chainID]. + // + // - [chainID] specifies the chain to be exporting the funds to. + // - [outputs] specifies the outputs to send to the [chainID]. + IssueExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + options ...common.Option, + ) (*evm.Tx, error) + + // IssueUnsignedTx signs and issues the unsigned tx. + IssueUnsignedAtomicTx( + utx evm.UnsignedAtomicTx, + options ...common.Option, + ) (*evm.Tx, error) + + // IssueAtomicTx issues the signed tx. + IssueAtomicTx( + tx *evm.Tx, + options ...common.Option, + ) error +} + +func NewWallet( + builder Builder, + signer Signer, + avaxClient evm.Client, + ethClient ethclient.Client, + backend Backend, +) Wallet { + return &wallet{ + Backend: backend, + builder: builder, + signer: signer, + avaxClient: avaxClient, + ethClient: ethClient, + } +} + +type wallet struct { + Backend + builder Builder + signer Signer + avaxClient evm.Client + ethClient ethclient.Client +} + +func (w *wallet) Builder() Builder { + return w.builder +} + +func (w *wallet) Signer() Signer { + return w.signer +} + +func (w *wallet) IssueImportTx( + chainID ids.ID, + to ethcommon.Address, + options ...common.Option, +) (*evm.Tx, error) { + baseFee, err := w.baseFee(options) + if err != nil { + return nil, err + } + + utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) + if err != nil { + return nil, err + } + return w.IssueUnsignedAtomicTx(utx, options...) +} + +func (w *wallet) IssueExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + options ...common.Option, +) (*evm.Tx, error) { + baseFee, err := w.baseFee(options) + if err != nil { + return nil, err + } + + utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) + if err != nil { + return nil, err + } + return w.IssueUnsignedAtomicTx(utx, options...) +} + +func (w *wallet) IssueUnsignedAtomicTx( + utx evm.UnsignedAtomicTx, + options ...common.Option, +) (*evm.Tx, error) { + ops := common.NewOptions(options) + ctx := ops.Context() + tx, err := w.signer.SignUnsignedAtomic(ctx, utx) + if err != nil { + return nil, err + } + + return tx, w.IssueAtomicTx(tx, options...) +} + +func (w *wallet) IssueAtomicTx( + tx *evm.Tx, + options ...common.Option, +) error { + ops := common.NewOptions(options) + ctx := ops.Context() + txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) + if err != nil { + return err + } + + if f := ops.PostIssuanceFunc(); f != nil { + f(txID) + } + + if ops.AssumeDecided() { + return w.Backend.AcceptAtomicTx(ctx, tx) + } + + pollFrequency := ops.PollFrequency() + ticker := time.NewTicker(pollFrequency) + defer ticker.Stop() + + for { + status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) + if err != nil { + return err + } + + switch status { + case evm.Accepted: + return w.Backend.AcceptAtomicTx(ctx, tx) + case evm.Dropped, evm.Unknown: + return errNotCommitted + } + + // The tx is Processing. + + select { + case <-ticker.C: + case <-ctx.Done(): + return ctx.Err() + } + } +} + +func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { + ops := common.NewOptions(options) + baseFee := ops.BaseFee(nil) + if baseFee != nil { + return baseFee, nil + } + + ctx := ops.Context() + return w.ethClient.EstimateBaseFee(ctx) +} diff --git a/wallet/chain/c/wallet_with_options.go b/wallet/chain/c/wallet_with_options.go index fd69a6d4fd02..7d6193683d49 100644 --- a/wallet/chain/c/wallet_with_options.go +++ b/wallet/chain/c/wallet_with_options.go @@ -3,80 +3,80 @@ package c -// import ( -// "github.com/ava-labs/coreth/plugin/evm" +import ( + "github.com/ava-labs/coreth/plugin/evm" -// ethcommon "github.com/ethereum/go-ethereum/common" + ethcommon "github.com/ethereum/go-ethereum/common" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) -// var _ Wallet = (*walletWithOptions)(nil) +var _ Wallet = (*walletWithOptions)(nil) -// func NewWalletWithOptions( -// wallet Wallet, -// options ...common.Option, -// ) Wallet { -// return &walletWithOptions{ -// Wallet: wallet, -// options: options, -// } -// } +func NewWalletWithOptions( + wallet Wallet, + options ...common.Option, +) Wallet { + return &walletWithOptions{ + Wallet: wallet, + options: options, + } +} -// type walletWithOptions struct { -// Wallet -// options []common.Option -// } +type walletWithOptions struct { + Wallet + options []common.Option +} -// func (w *walletWithOptions) Builder() Builder { -// return NewBuilderWithOptions( -// w.Wallet.Builder(), -// w.options..., -// ) -// } +func (w *walletWithOptions) Builder() Builder { + return NewBuilderWithOptions( + w.Wallet.Builder(), + w.options..., + ) +} -// func (w *walletWithOptions) IssueImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// options ...common.Option, -// ) (*evm.Tx, error) { -// return w.Wallet.IssueImportTx( -// chainID, -// to, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueImportTx( + chainID ids.ID, + to ethcommon.Address, + options ...common.Option, +) (*evm.Tx, error) { + return w.Wallet.IssueImportTx( + chainID, + to, + common.UnionOptions(w.options, options)..., + ) +} -// func (w *walletWithOptions) IssueExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// options ...common.Option, -// ) (*evm.Tx, error) { -// return w.Wallet.IssueExportTx( -// chainID, -// outputs, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + options ...common.Option, +) (*evm.Tx, error) { + return w.Wallet.IssueExportTx( + chainID, + outputs, + common.UnionOptions(w.options, options)..., + ) +} -// func (w *walletWithOptions) IssueUnsignedAtomicTx( -// utx evm.UnsignedAtomicTx, -// options ...common.Option, -// ) (*evm.Tx, error) { -// return w.Wallet.IssueUnsignedAtomicTx( -// utx, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueUnsignedAtomicTx( + utx evm.UnsignedAtomicTx, + options ...common.Option, +) (*evm.Tx, error) { + return w.Wallet.IssueUnsignedAtomicTx( + utx, + common.UnionOptions(w.options, options)..., + ) +} -// func (w *walletWithOptions) IssueAtomicTx( -// tx *evm.Tx, -// options ...common.Option, -// ) error { -// return w.Wallet.IssueAtomicTx( -// tx, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueAtomicTx( + tx *evm.Tx, + options ...common.Option, +) error { + return w.Wallet.IssueAtomicTx( + tx, + common.UnionOptions(w.options, options)..., + ) +} diff --git a/wallet/subnet/primary/api.go b/wallet/subnet/primary/api.go index 402b79989d17..3ac72c217884 100644 --- a/wallet/subnet/primary/api.go +++ b/wallet/subnet/primary/api.go @@ -5,12 +5,12 @@ package primary import ( "context" - // "fmt" + "fmt" - // "github.com/ava-labs/coreth/ethclient" - // "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/coreth/ethclient" + "github.com/ava-labs/coreth/plugin/evm" - // "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common" "github.com/ava-labs/avalanchego/api/info" "github.com/ava-labs/avalanchego/codec" @@ -22,8 +22,7 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm" "github.com/ava-labs/avalanchego/vms/platformvm/txs" - - // "github.com/ava-labs/avalanchego/wallet/chain/c" + "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" ) @@ -60,9 +59,9 @@ type AVAXState struct { PCTX p.Context XClient avm.Client XCTX x.Context - // CClient evm.Client - // CCTX c.Context - UTXOs UTXOs + CClient evm.Client + CCTX c.Context + UTXOs UTXOs } func FetchState( @@ -76,7 +75,7 @@ func FetchState( infoClient := info.NewClient(uri) pClient := platformvm.NewClient(uri) xClient := avm.NewClient(uri, "X") - // cClient := evm.NewCChainClient(uri) + cClient := evm.NewCChainClient(uri) pCTX, err := p.NewContextFromClients(ctx, infoClient, xClient) if err != nil { @@ -88,10 +87,10 @@ func FetchState( return nil, err } - // cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) - // if err != nil { - // return nil, err - // } + cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) + if err != nil { + return nil, err + } utxos := NewUTXOs() addrList := addrs.List() @@ -110,11 +109,11 @@ func FetchState( client: xClient, codec: x.Parser.Codec(), }, - // { - // id: cCTX.BlockchainID(), - // client: cClient, - // codec: evm.Codec, - // }, + { + id: cCTX.BlockchainID(), + client: cClient, + codec: evm.Codec, + }, } for _, destinationChain := range chains { for _, sourceChain := range chains { @@ -137,52 +136,52 @@ func FetchState( PCTX: pCTX, XClient: xClient, XCTX: xCTX, - // CClient: cClient, - // CCTX: cCTX, - UTXOs: utxos, + CClient: cClient, + CCTX: cCTX, + UTXOs: utxos, }, nil } -// type EthState struct { -// Client ethclient.Client -// Accounts map[common.Address]*c.Account -// } - -// func FetchEthState( -// ctx context.Context, -// uri string, -// addrs set.Set[common.Address], -// ) (*EthState, error) { -// path := fmt.Sprintf( -// "%s/ext/%s/C/rpc", -// uri, -// constants.ChainAliasPrefix, -// ) -// client, err := ethclient.Dial(path) -// if err != nil { -// return nil, err -// } - -// accounts := make(map[common.Address]*c.Account, addrs.Len()) -// for addr := range addrs { -// balance, err := client.BalanceAt(ctx, addr, nil) -// if err != nil { -// return nil, err -// } -// nonce, err := client.NonceAt(ctx, addr, nil) -// if err != nil { -// return nil, err -// } -// accounts[addr] = &c.Account{ -// Balance: balance, -// Nonce: nonce, -// } -// } -// return &EthState{ -// Client: client, -// Accounts: accounts, -// }, nil -// } +type EthState struct { + Client ethclient.Client + Accounts map[common.Address]*c.Account +} + +func FetchEthState( + ctx context.Context, + uri string, + addrs set.Set[common.Address], +) (*EthState, error) { + path := fmt.Sprintf( + "%s/ext/%s/C/rpc", + uri, + constants.ChainAliasPrefix, + ) + client, err := ethclient.Dial(path) + if err != nil { + return nil, err + } + + accounts := make(map[common.Address]*c.Account, addrs.Len()) + for addr := range addrs { + balance, err := client.BalanceAt(ctx, addr, nil) + if err != nil { + return nil, err + } + nonce, err := client.NonceAt(ctx, addr, nil) + if err != nil { + return nil, err + } + accounts[addr] = &c.Account{ + Balance: balance, + Nonce: nonce, + } + } + return &EthState{ + Client: client, + Accounts: accounts, + }, nil +} // AddAllUTXOs fetches all the UTXOs referenced by [addresses] that were sent // from [sourceChainID] to [destinationChainID] from the [client]. It then uses diff --git a/wallet/subnet/primary/example_test.go b/wallet/subnet/primary/example_test.go index 4a73e8c070b2..483c049d4ac0 100644 --- a/wallet/subnet/primary/example_test.go +++ b/wallet/subnet/primary/example_test.go @@ -30,7 +30,7 @@ func ExampleWallet() { wallet, err := MakeWallet(ctx, &WalletConfig{ URI: LocalAPIURI, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet with: %s\n", err) diff --git a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go index 21c081d2982b..d5e8ce422307 100644 --- a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go @@ -46,9 +46,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/add-primary-validator/main.go b/wallet/subnet/primary/examples/add-primary-validator/main.go index 13c28f995f63..a56dae23db3a 100644 --- a/wallet/subnet/primary/examples/add-primary-validator/main.go +++ b/wallet/subnet/primary/examples/add-primary-validator/main.go @@ -45,7 +45,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/c-chain-export/main.go b/wallet/subnet/primary/examples/c-chain-export/main.go index a6b9a0c810b8..fec55c899feb 100644 --- a/wallet/subnet/primary/examples/c-chain-export/main.go +++ b/wallet/subnet/primary/examples/c-chain-export/main.go @@ -3,70 +3,70 @@ package main -// import ( -// "context" -// "log" -// "time" +import ( + "context" + "log" + "time" -// "github.com/ava-labs/avalanchego/genesis" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary" -// ) + "github.com/ava-labs/avalanchego/genesis" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary" +) -// func main() { -// key := genesis.EWOQKey -// uri := primary.LocalAPIURI -// kc := secp256k1fx.NewKeychain(key) -// avaxAddr := key.Address() +func main() { + key := genesis.EWOQKey + uri := primary.LocalAPIURI + kc := secp256k1fx.NewKeychain(key) + avaxAddr := key.Address() -// ctx := context.Background() + ctx := context.Background() -// // MakeWallet fetches the available UTXOs owned by [kc] on the network that -// // [uri] is hosting. -// walletSyncStartTime := time.Now() -// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ -// URI: uri, -// AVAXKeychain: kc, -// EthKeychain: kc, -// }) -// if err != nil { -// log.Fatalf("failed to initialize wallet: %s\n", err) -// } -// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) + // MakeWallet fetches the available UTXOs owned by [kc] on the network that + // [uri] is hosting. + walletSyncStartTime := time.Now() + wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, + }) + if err != nil { + log.Fatalf("failed to initialize wallet: %s\n", err) + } + log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) -// // Get the P-chain wallet -// pWallet := wallet.P() -// cWallet := wallet.C() + // Get the P-chain wallet + pWallet := wallet.P() + cWallet := wallet.C() -// // Pull out useful constants to use when issuing transactions. -// cChainID := cWallet.BlockchainID() -// owner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// avaxAddr, -// }, -// } + // Pull out useful constants to use when issuing transactions. + cChainID := cWallet.BlockchainID() + owner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + avaxAddr, + }, + } -// exportStartTime := time.Now() -// exportTx, err := cWallet.IssueExportTx( -// constants.PlatformChainID, -// []*secp256k1fx.TransferOutput{{ -// Amt: units.Avax, -// OutputOwners: owner, -// }}, -// ) -// if err != nil { -// log.Fatalf("failed to issue export transaction: %s\n", err) -// } -// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) + exportStartTime := time.Now() + exportTx, err := cWallet.IssueExportTx( + constants.PlatformChainID, + []*secp256k1fx.TransferOutput{{ + Amt: units.Avax, + OutputOwners: owner, + }}, + ) + if err != nil { + log.Fatalf("failed to issue export transaction: %s\n", err) + } + log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) -// importStartTime := time.Now() -// importTx, err := pWallet.IssueImportTx(cChainID, &owner) -// if err != nil { -// log.Fatalf("failed to issue import transaction: %s\n", err) -// } -// log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) -// } + importStartTime := time.Now() + importTx, err := pWallet.IssueImportTx(cChainID, &owner) + if err != nil { + log.Fatalf("failed to issue import transaction: %s\n", err) + } + log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) +} diff --git a/wallet/subnet/primary/examples/c-chain-import/main.go b/wallet/subnet/primary/examples/c-chain-import/main.go index 2d9b8a244cb0..b4dc4e603eb3 100644 --- a/wallet/subnet/primary/examples/c-chain-import/main.go +++ b/wallet/subnet/primary/examples/c-chain-import/main.go @@ -3,75 +3,75 @@ package main -// import ( -// "context" -// "log" -// "time" +import ( + "context" + "log" + "time" -// "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/coreth/plugin/evm" -// "github.com/ava-labs/avalanchego/genesis" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary" -// ) + "github.com/ava-labs/avalanchego/genesis" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary" +) -// func main() { -// key := genesis.EWOQKey -// uri := primary.LocalAPIURI -// kc := secp256k1fx.NewKeychain(key) -// avaxAddr := key.Address() -// ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) +func main() { + key := genesis.EWOQKey + uri := primary.LocalAPIURI + kc := secp256k1fx.NewKeychain(key) + avaxAddr := key.Address() + ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) -// ctx := context.Background() + ctx := context.Background() -// // MakeWallet fetches the available UTXOs owned by [kc] on the network that -// // [uri] is hosting. -// walletSyncStartTime := time.Now() -// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ -// URI: uri, -// AVAXKeychain: kc, -// EthKeychain: kc, -// }) -// if err != nil { -// log.Fatalf("failed to initialize wallet: %s\n", err) -// } -// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) + // MakeWallet fetches the available UTXOs owned by [kc] on the network that + // [uri] is hosting. + walletSyncStartTime := time.Now() + wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, + }) + if err != nil { + log.Fatalf("failed to initialize wallet: %s\n", err) + } + log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) -// // Get the P-chain wallet -// pWallet := wallet.P() -// cWallet := wallet.C() + // Get the P-chain wallet + pWallet := wallet.P() + cWallet := wallet.C() -// // Pull out useful constants to use when issuing transactions. -// cChainID := cWallet.BlockchainID() -// avaxAssetID := cWallet.AVAXAssetID() -// owner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// avaxAddr, -// }, -// } + // Pull out useful constants to use when issuing transactions. + cChainID := cWallet.BlockchainID() + avaxAssetID := cWallet.AVAXAssetID() + owner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + avaxAddr, + }, + } -// exportStartTime := time.Now() -// exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ -// Asset: avax.Asset{ID: avaxAssetID}, -// Out: &secp256k1fx.TransferOutput{ -// Amt: units.Avax, -// OutputOwners: owner, -// }, -// }}) -// if err != nil { -// log.Fatalf("failed to issue export transaction: %s\n", err) -// } -// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) + exportStartTime := time.Now() + exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ + Asset: avax.Asset{ID: avaxAssetID}, + Out: &secp256k1fx.TransferOutput{ + Amt: units.Avax, + OutputOwners: owner, + }, + }}) + if err != nil { + log.Fatalf("failed to issue export transaction: %s\n", err) + } + log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) -// importStartTime := time.Now() -// importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) -// if err != nil { -// log.Fatalf("failed to issue import transaction: %s\n", err) -// } -// log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) -// } + importStartTime := time.Now() + importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) + if err != nil { + log.Fatalf("failed to issue import transaction: %s\n", err) + } + log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) +} diff --git a/wallet/subnet/primary/examples/create-asset/main.go b/wallet/subnet/primary/examples/create-asset/main.go index 0bccfbb5fc52..30804f083df6 100644 --- a/wallet/subnet/primary/examples/create-asset/main.go +++ b/wallet/subnet/primary/examples/create-asset/main.go @@ -30,7 +30,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-chain/main.go b/wallet/subnet/primary/examples/create-chain/main.go index 521a3cca53cf..5e6898a1b649 100644 --- a/wallet/subnet/primary/examples/create-chain/main.go +++ b/wallet/subnet/primary/examples/create-chain/main.go @@ -41,9 +41,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/create-locked-stakeable/main.go b/wallet/subnet/primary/examples/create-locked-stakeable/main.go index 92f1b5cb0e1b..e688968e9e8a 100644 --- a/wallet/subnet/primary/examples/create-locked-stakeable/main.go +++ b/wallet/subnet/primary/examples/create-locked-stakeable/main.go @@ -39,7 +39,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-subnet/main.go b/wallet/subnet/primary/examples/create-subnet/main.go index 3e8d69bc016a..add98ea7931c 100644 --- a/wallet/subnet/primary/examples/create-subnet/main.go +++ b/wallet/subnet/primary/examples/create-subnet/main.go @@ -28,7 +28,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/remove-subnet-validator/main.go b/wallet/subnet/primary/examples/remove-subnet-validator/main.go index 46f4b85124db..2842c7c0a790 100644 --- a/wallet/subnet/primary/examples/remove-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/remove-subnet-validator/main.go @@ -38,9 +38,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/wallet.go b/wallet/subnet/primary/wallet.go index ae5e4202a099..54de390d029c 100644 --- a/wallet/subnet/primary/wallet.go +++ b/wallet/subnet/primary/wallet.go @@ -11,8 +11,7 @@ import ( "github.com/ava-labs/avalanchego/utils/crypto/keychain" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/platformvm/txs" - - // "github.com/ava-labs/avalanchego/wallet/chain/c" + "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" @@ -24,13 +23,13 @@ var _ Wallet = (*wallet)(nil) type Wallet interface { P() p.Wallet X() x.Wallet - // C() c.Wallet + C() c.Wallet } type wallet struct { p p.Wallet x x.Wallet - // c c.Wallet + c c.Wallet } func (w *wallet) P() p.Wallet { @@ -41,16 +40,16 @@ func (w *wallet) X() x.Wallet { return w.x } -// func (w *wallet) C() c.Wallet { -// return w.c -// } +func (w *wallet) C() c.Wallet { + return w.c +} // Creates a new default wallet -func NewWallet(p p.Wallet, x x.Wallet /*, c c.Wallet*/) Wallet { +func NewWallet(p p.Wallet, x x.Wallet, c c.Wallet) Wallet { return &wallet{ p: p, x: x, - // c: c, + c: c, } } @@ -59,7 +58,7 @@ func NewWalletWithOptions(w Wallet, options ...common.Option) Wallet { return NewWallet( p.NewWalletWithOptions(w.P(), options...), x.NewWalletWithOptions(w.X(), options...), - // c.NewWalletWithOptions(w.C(), options...), + c.NewWalletWithOptions(w.C(), options...), ) } @@ -68,7 +67,7 @@ type WalletConfig struct { URI string // required // Keys to use for signing all transactions. AVAXKeychain keychain.Keychain // required - // EthKeychain c.EthKeychain // required + EthKeychain c.EthKeychain // required // Set of P-chain transactions that the wallet should know about to be able // to generate transactions. PChainTxs map[ids.ID]*txs.Tx // optional @@ -94,11 +93,11 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { return nil, err } - // ethAddrs := config.EthKeychain.EthAddresses() - // ethState, err := FetchEthState(ctx, config.URI, ethAddrs) - // if err != nil { - // return nil, err - // } + ethAddrs := config.EthKeychain.EthAddresses() + ethState, err := FetchEthState(ctx, config.URI, ethAddrs) + if err != nil { + return nil, err + } pChainTxs := config.PChainTxs if pChainTxs == nil { @@ -128,15 +127,15 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { xBuilder := x.NewBuilder(avaxAddrs, xBackend) xSigner := x.NewSigner(config.AVAXKeychain, xBackend) - // cChainID := avaxState.CCTX.BlockchainID() - // cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) - // cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) - // cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) - // cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) + cChainID := avaxState.CCTX.BlockchainID() + cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) + cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) + cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) + cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) return NewWallet( p.NewWallet(pBuilder, pSigner, avaxState.PClient, pBackend), x.NewWallet(xBuilder, xSigner, avaxState.XClient, xBackend), - // c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), + c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), ), nil } From 54ff2524a1d6266be88316ec6c828a6424c0b348 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 26 Oct 2023 15:57:55 +0200 Subject: [PATCH 05/36] proposervm backfilling scaffolding --- .../engine/snowman/block/state_syncable_vm.go | 4 +++ vms/proposervm/state_syncable_vm.go | 26 ++++++++++++++----- vms/proposervm/vm.go | 4 +++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/snow/engine/snowman/block/state_syncable_vm.go b/snow/engine/snowman/block/state_syncable_vm.go index efce7243b78f..828418cd92e6 100644 --- a/snow/engine/snowman/block/state_syncable_vm.go +++ b/snow/engine/snowman/block/state_syncable_vm.go @@ -45,6 +45,10 @@ type StateSyncableVM interface { // [summaryHeight]. GetStateSummary(ctx context.Context, summaryHeight uint64) (StateSummary, error) + // BackfillBlocksEnabled checks if VM wants to download all blocks from state summary one + // down to genesis. + // + // Returns ids.EmptyID if block backfilling is not enabled. BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) BackfillBlocks(ctx context.Context, blocks [][]byte) error diff --git a/vms/proposervm/state_syncable_vm.go b/vms/proposervm/state_syncable_vm.go index 02f0f4694ee5..7221ea9e0e04 100644 --- a/vms/proposervm/state_syncable_vm.go +++ b/vms/proposervm/state_syncable_vm.go @@ -5,7 +5,6 @@ package proposervm import ( "context" - "errors" "fmt" "go.uber.org/zap" @@ -162,12 +161,27 @@ func (vm *VM) buildStateSummary(ctx context.Context, innerSummary block.StateSum }, nil } -var errNotYetImplemented = errors.New("backfilling not yet implemented") +func (vm *VM) BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) { + if vm.ssVM == nil { + return ids.Empty, nil + } -func (*VM) BackfillBlocksEnabled(context.Context) (ids.ID, error) { - return ids.Empty, errNotYetImplemented + return vm.ssVM.BackfillBlocksEnabled(ctx) } -func (*VM) BackfillBlocks(context.Context, [][]byte) error { - return errNotYetImplemented +func (vm *VM) BackfillBlocks(ctx context.Context, blksBytes [][]byte) error { + innerBlksBytes := make([][]byte, 0, len(blksBytes)) + for i, blkBytes := range blksBytes { + blk, err := vm.parseProposerBlock(ctx, blkBytes) + if err != nil { + return fmt.Errorf("failed parsing backfilled block, index %d, %w", i, err) + } + // TODO: consider validating that block is at least below last accepted block + // or that block has not been stored yet + if err := blk.acceptOuterBlk(); err != nil { + return err + } + innerBlksBytes = append(innerBlksBytes, blk.getInnerBlk().Bytes()) + } + return vm.ssVM.BackfillBlocks(ctx, innerBlksBytes) } diff --git a/vms/proposervm/vm.go b/vms/proposervm/vm.go index a101be86f574..1bfdf13da0a5 100644 --- a/vms/proposervm/vm.go +++ b/vms/proposervm/vm.go @@ -327,6 +327,10 @@ func (vm *VM) BuildBlock(ctx context.Context) (snowman.Block, error) { } func (vm *VM) ParseBlock(ctx context.Context, b []byte) (snowman.Block, error) { + return vm.parseProposerBlock(ctx, b) +} + +func (vm *VM) parseProposerBlock(ctx context.Context, b []byte) (Block, error) { if blk, err := vm.parsePostForkBlock(ctx, b); err == nil { return blk, nil } From 3ba03dc9181304eca7ac89046a576c1809b25b33 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 26 Oct 2023 16:13:46 +0200 Subject: [PATCH 06/36] rpcchainvm backfilling scaffolding --- vms/rpcchainvm/vm_server.go | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/vms/rpcchainvm/vm_server.go b/vms/rpcchainvm/vm_server.go index 21b21ccfbbb0..d40c5cf84245 100644 --- a/vms/rpcchainvm/vm_server.go +++ b/vms/rpcchainvm/vm_server.go @@ -821,14 +821,30 @@ func (vm *VMServer) GetStateSummary( }, nil } -var errNotYetImplemented = errors.New("backfilling not yet implemented") +func (vm *VMServer) BackfillBlocksEnabled(ctx context.Context, _ *emptypb.Empty) (*vmpb.BackfillBlocksEnabledResponse, error) { + var ( + blkID = ids.Empty + err error + ) + if vm.ssVM != nil { + blkID, err = vm.ssVM.BackfillBlocksEnabled(ctx) + } -func (*VMServer) BackfillBlocksEnabled(context.Context, *emptypb.Empty) (*vmpb.BackfillBlocksEnabledResponse, error) { - return &vmpb.BackfillBlocksEnabledResponse{}, errNotYetImplemented + return &vmpb.BackfillBlocksEnabledResponse{ + Id: blkID[:], + Err: errorToErrEnum[err], + }, errorToRPCError(err) } -func (*VMServer) BackfillBlocks(context.Context, *vmpb.BackfillBlocksRequest) (*vmpb.BackfillBlocksResponse, error) { - return &vmpb.BackfillBlocksResponse{}, errNotYetImplemented +func (vm *VMServer) BackfillBlocks(ctx context.Context, req *vmpb.BackfillBlocksRequest) (*vmpb.BackfillBlocksResponse, error) { + var err error + if vm.ssVM != nil { + err = vm.ssVM.BackfillBlocks(ctx, req.BlksBytes) + } + + return &vmpb.BackfillBlocksResponse{ + Err: errorToErrEnum[err], + }, errorToRPCError(err) } func (vm *VMServer) BlockVerify(ctx context.Context, req *vmpb.BlockVerifyRequest) (*vmpb.BlockVerifyResponse, error) { From 58647b416af4c6e7087c8cc2d1f4b614ae6243d2 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 30 Oct 2023 09:55:56 +0100 Subject: [PATCH 07/36] wip: block backfilling scaffolding --- chains/manager.go | 3 + .../engine/snowman/block/state_syncable_vm.go | 1 + snow/engine/snowman/config.go | 4 ++ snow/engine/snowman/config_test.go | 2 + snow/engine/snowman/transitive.go | 67 ++++++++++++++++++- 5 files changed, 76 insertions(+), 1 deletion(-) diff --git a/chains/manager.go b/chains/manager.go index 2234e82aadcc..4ba8cf1533ed 100644 --- a/chains/manager.go +++ b/chains/manager.go @@ -878,6 +878,8 @@ func (m *manager) createAvalancheChain( Validators: vdrs, Params: consensusParams, Consensus: snowmanConsensus, + + Peers: connectedBeacons, } snowmanEngine, err := smeng.New(snowmanEngineConfig) if err != nil { @@ -1231,6 +1233,7 @@ func (m *manager) createSnowmanChain( Params: consensusParams, Consensus: consensus, PartialSync: m.PartialSyncPrimaryNetwork && commonCfg.Ctx.ChainID == constants.PlatformChainID, + Peers: connectedBeacons, } engine, err := smeng.New(engineConfig) if err != nil { diff --git a/snow/engine/snowman/block/state_syncable_vm.go b/snow/engine/snowman/block/state_syncable_vm.go index 828418cd92e6..82493fab374d 100644 --- a/snow/engine/snowman/block/state_syncable_vm.go +++ b/snow/engine/snowman/block/state_syncable_vm.go @@ -49,6 +49,7 @@ type StateSyncableVM interface { // down to genesis. // // Returns ids.EmptyID if block backfilling is not enabled. + // TODO ABENEGIA: Use error instead of the EmptyID BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) BackfillBlocks(ctx context.Context, blocks [][]byte) error diff --git a/snow/engine/snowman/config.go b/snow/engine/snowman/config.go index ed63af2f4936..cbd2a8e8d001 100644 --- a/snow/engine/snowman/config.go +++ b/snow/engine/snowman/config.go @@ -8,6 +8,7 @@ import ( "github.com/ava-labs/avalanchego/snow/consensus/snowball" "github.com/ava-labs/avalanchego/snow/consensus/snowman" "github.com/ava-labs/avalanchego/snow/engine/common" + "github.com/ava-labs/avalanchego/snow/engine/common/tracker" "github.com/ava-labs/avalanchego/snow/engine/snowman/block" "github.com/ava-labs/avalanchego/snow/validators" ) @@ -23,4 +24,7 @@ type Config struct { Params snowball.Parameters Consensus snowman.Consensus PartialSync bool + + // used for block-backfilling + Peers tracker.Peers } diff --git a/snow/engine/snowman/config_test.go b/snow/engine/snowman/config_test.go index 54d9536a4884..f03b34259e04 100644 --- a/snow/engine/snowman/config_test.go +++ b/snow/engine/snowman/config_test.go @@ -30,5 +30,7 @@ func DefaultConfigs() Config { MaxItemProcessingTime: 1, }, Consensus: &snowman.Topological{}, + + Peers: commonCfg.StartupTracker, } } diff --git a/snow/engine/snowman/transitive.go b/snow/engine/snowman/transitive.go index d7d62e098110..2698faf772ae 100644 --- a/snow/engine/snowman/transitive.go +++ b/snow/engine/snowman/transitive.go @@ -20,6 +20,7 @@ import ( "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/snow/engine/common/tracker" "github.com/ava-labs/avalanchego/snow/engine/snowman/ancestor" + "github.com/ava-labs/avalanchego/snow/engine/snowman/block" "github.com/ava-labs/avalanchego/snow/event" "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils/bag" @@ -29,6 +30,7 @@ import ( "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/utils/units" "github.com/ava-labs/avalanchego/utils/wrappers" + "github.com/ava-labs/avalanchego/version" ) const nonVerifiedCacheSize = 64 * units.MiB @@ -92,6 +94,12 @@ type Transitive struct { // errs tracks if an error has occurred in a callback errs wrappers.Errs + + // START OF BLOCK BACKFILLING STUFF + fetchFrom set.Set[ids.NodeID] // picked from bootstrapper + peers tracker.Peers + + // END OF BLOCK BACKFILLING STUFF } func newTransitive(config Config) (*Transitive, error) { @@ -135,6 +143,10 @@ func newTransitive(config Config) (*Transitive, error) { "", config.Ctx.Registerer, ), + + // block-backfilling stuff + fetchFrom: set.Of[ids.NodeID](config.Validators.GetValidatorIDs(config.Ctx.SubnetID)...), + peers: config.Peers, } return t, t.metrics.Initialize("", config.Ctx.Registerer) @@ -454,7 +466,10 @@ func (t *Transitive) Start(ctx context.Context, startReqID uint32) error { err) } - return nil + // Start Block backfilling if needed + // TODO: for now we extend transitive engine with backfilling features + // Later on we'll repackage them into a separate struct to be moved in syncer package. + return t.startBlockBackfilling(ctx) } func (t *Transitive) HealthCheck(ctx context.Context) (interface{}, error) { @@ -992,3 +1007,53 @@ func (t *Transitive) addUnverifiedBlockToConsensus(ctx context.Context, blk snow tree: t.nonVerifieds, }) } + +// BLOCK BACKFILLING STUFF +func (t *Transitive) startBlockBackfilling(ctx context.Context) error { + ssVM, ok := t.VM.(block.StateSyncableVM) + if !ok { + return nil // nothing to do + } + + switch blkID, err := ssVM.BackfillBlocksEnabled(ctx); { + case err != nil: + return fmt.Errorf("failed checking if state sync block backfilling is enabled: %w", err) + case blkID == ids.Empty: + t.Ctx.Log.Info("block backfilling not enabled") + return nil + default: + validatorID, ok := t.fetchFrom.Peek() + if !ok { + return fmt.Errorf("dropping request for %s as there are no nodes to request blkID from", blkID) + } + + // We only allow one outbound request at a time from a node + t.markUnavailable(validatorID) + t.RequestID++ + t.Sender.SendGetAncestors(ctx, validatorID, t.RequestID, blkID) + return nil + } +} + +func (t *Transitive) markUnavailable(nodeID ids.NodeID) { + t.fetchFrom.Remove(nodeID) + + // if [fetchFrom] has become empty, reset it to the currently preferred + // peers + if t.fetchFrom.Len() == 0 { + t.fetchFrom = t.peers.PreferredPeers() + } +} + +func (t *Transitive) Connected(ctx context.Context, nodeID ids.NodeID, nodeVersion *version.Application) error { + // Ensure fetchFrom reflects proper validator list + if _, ok := t.Validators.GetValidator(t.Ctx.SubnetID, nodeID); ok { + t.fetchFrom.Add(nodeID) + } + return t.Connector.Connected(ctx, nodeID, nodeVersion) +} + +func (t *Transitive) Disconnected(ctx context.Context, nodeID ids.NodeID) error { + t.markUnavailable(nodeID) + return t.Connector.Disconnected(ctx, nodeID) +} From 397ce7d1df718920e8bac3f8501207fa13dd9151 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 30 Oct 2023 11:00:50 +0100 Subject: [PATCH 08/36] wip: block backfilling scaffolding --- chains/manager.go | 11 +- .../engine/snowman/block/state_syncable_vm.go | 7 + snow/engine/snowman/config.go | 4 +- snow/engine/snowman/transitive.go | 124 +++++++++++++++--- 4 files changed, 123 insertions(+), 23 deletions(-) diff --git a/chains/manager.go b/chains/manager.go index 4ba8cf1533ed..4bba3ff5df57 100644 --- a/chains/manager.go +++ b/chains/manager.go @@ -879,7 +879,10 @@ func (m *manager) createAvalancheChain( Params: consensusParams, Consensus: snowmanConsensus, - Peers: connectedBeacons, + // block backfilling stuff + Peers: connectedBeacons, + AncestorsMaxContainersSent: m.BootstrapAncestorsMaxContainersSent, + AncestorsMaxContainersReceived: m.BootstrapAncestorsMaxContainersReceived, } snowmanEngine, err := smeng.New(snowmanEngineConfig) if err != nil { @@ -1233,7 +1236,11 @@ func (m *manager) createSnowmanChain( Params: consensusParams, Consensus: consensus, PartialSync: m.PartialSyncPrimaryNetwork && commonCfg.Ctx.ChainID == constants.PlatformChainID, - Peers: connectedBeacons, + + // block backfilling stuff + Peers: connectedBeacons, + AncestorsMaxContainersSent: m.BootstrapAncestorsMaxContainersSent, + AncestorsMaxContainersReceived: m.BootstrapAncestorsMaxContainersReceived, } engine, err := smeng.New(engineConfig) if err != nil { diff --git a/snow/engine/snowman/block/state_syncable_vm.go b/snow/engine/snowman/block/state_syncable_vm.go index 82493fab374d..c8868c07d598 100644 --- a/snow/engine/snowman/block/state_syncable_vm.go +++ b/snow/engine/snowman/block/state_syncable_vm.go @@ -52,5 +52,12 @@ type StateSyncableVM interface { // TODO ABENEGIA: Use error instead of the EmptyID BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) + // BackfillBlocks pass blocks bytes retrieved via GetAncestors calls to the VM + // It's left to the VM the duty to parse and validate the blocks. + // BackfillBlocks returns the next block ID to be requested and an error + // Upon error, engine will issue a GetAncestor call to a different peer + // with the previously requested block ID + // If BackfillBlocks returns a block known to the VM, the engine will + // stop asking for blocks ancestors. (TODO: consider using a boolean or an empty blockID) BackfillBlocks(ctx context.Context, blocks [][]byte) error } diff --git a/snow/engine/snowman/config.go b/snow/engine/snowman/config.go index cbd2a8e8d001..1cdf5faa8c04 100644 --- a/snow/engine/snowman/config.go +++ b/snow/engine/snowman/config.go @@ -26,5 +26,7 @@ type Config struct { PartialSync bool // used for block-backfilling - Peers tracker.Peers + Peers tracker.Peers + AncestorsMaxContainersSent int + AncestorsMaxContainersReceived int } diff --git a/snow/engine/snowman/transitive.go b/snow/engine/snowman/transitive.go index 2698faf772ae..cfa204123790 100644 --- a/snow/engine/snowman/transitive.go +++ b/snow/engine/snowman/transitive.go @@ -22,7 +22,6 @@ import ( "github.com/ava-labs/avalanchego/snow/engine/snowman/ancestor" "github.com/ava-labs/avalanchego/snow/engine/snowman/block" "github.com/ava-labs/avalanchego/snow/event" - "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils/bag" "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/logging" @@ -56,9 +55,7 @@ type Transitive struct { common.AcceptedStateSummaryHandler common.AcceptedFrontierHandler common.AcceptedHandler - common.AncestorsHandler common.AppHandler - validators.Connector RequestID uint32 @@ -96,9 +93,9 @@ type Transitive struct { errs wrappers.Errs // START OF BLOCK BACKFILLING STUFF - fetchFrom set.Set[ids.NodeID] // picked from bootstrapper - peers tracker.Peers - + fetchFrom set.Set[ids.NodeID] // picked from bootstrapper + peers tracker.Peers + backfillingRequests common.Requests // tracks which validators were asked for which containers in which requests // END OF BLOCK BACKFILLING STUFF } @@ -130,9 +127,7 @@ func newTransitive(config Config) (*Transitive, error) { AcceptedStateSummaryHandler: common.NewNoOpAcceptedStateSummaryHandler(config.Ctx.Log), AcceptedFrontierHandler: common.NewNoOpAcceptedFrontierHandler(config.Ctx.Log), AcceptedHandler: common.NewNoOpAcceptedHandler(config.Ctx.Log), - AncestorsHandler: common.NewNoOpAncestorsHandler(config.Ctx.Log), AppHandler: config.VM, - Connector: config.VM, pending: make(map[ids.ID]snowman.Block), nonVerifieds: ancestor.NewTree(), nonVerifiedCache: nonVerifiedCache, @@ -1015,24 +1010,113 @@ func (t *Transitive) startBlockBackfilling(ctx context.Context) error { return nil // nothing to do } - switch blkID, err := ssVM.BackfillBlocksEnabled(ctx); { + switch wantedBlk, err := ssVM.BackfillBlocksEnabled(ctx); { case err != nil: return fmt.Errorf("failed checking if state sync block backfilling is enabled: %w", err) - case blkID == ids.Empty: + case wantedBlk == ids.Empty: t.Ctx.Log.Info("block backfilling not enabled") return nil default: - validatorID, ok := t.fetchFrom.Peek() - if !ok { - return fmt.Errorf("dropping request for %s as there are no nodes to request blkID from", blkID) - } + return t.fetch(ctx, wantedBlk) + } +} + +// Ancestors handles the receipt of multiple containers. Should be received in +// response to a GetAncestors message to [nodeID] with request ID [requestID] +func (t *Transitive) Ancestors(ctx context.Context, nodeID ids.NodeID, requestID uint32, blks [][]byte) error { + // Make sure this is in response to a request we made + wantedBlkID, ok := t.backfillingRequests.Remove(nodeID, requestID) + if !ok { // this message isn't in response to a request we made + t.Ctx.Log.Debug("received unexpected Ancestors", + zap.Stringer("nodeID", nodeID), + zap.Uint32("requestID", requestID), + ) + return nil + } + + lenBlks := len(blks) + if lenBlks == 0 { + t.Ctx.Log.Debug("received Ancestors with no block", + zap.Stringer("nodeID", nodeID), + zap.Uint32("requestID", requestID), + ) + + t.markUnavailable(nodeID) + + // Send another request for this + return t.fetch(ctx, wantedBlkID) + } + + // This node has responded - so add it back into the set + t.fetchFrom.Add(nodeID) + + if lenBlks > t.Config.AncestorsMaxContainersReceived { + blks = blks[:t.Config.AncestorsMaxContainersReceived] + t.Ctx.Log.Debug("ignoring containers in Ancestors", + zap.Int("numContainers", lenBlks-t.Config.AncestorsMaxContainersReceived), + zap.Stringer("nodeID", nodeID), + zap.Uint32("requestID", requestID), + ) + } + + ssVM, ok := t.VM.(block.StateSyncableVM) + if !ok { + return nil // nothing to do + } + + nextWantedBlkID, err := ssVM.BackfillBlocks(ctx, blks) + if err != nil { // the provided blocks couldn't be parsed + t.Ctx.Log.Debug("failed to parse blocks in Ancestors", + zap.Stringer("nodeID", nodeID), + zap.Uint32("requestID", requestID), + zap.Error(err), + ) + return t.fetch(ctx, wantedBlkID) + } + + return t.fetch(ctx, nextWantedBlkID) +} + +func (t *Transitive) GetAncestorsFailed(ctx context.Context, nodeID ids.NodeID, requestID uint32) error { + blkID, ok := t.backfillingRequests.Remove(nodeID, requestID) + if !ok { + t.Ctx.Log.Debug("unexpectedly called GetAncestorsFailed", + zap.Stringer("nodeID", nodeID), + zap.Uint32("requestID", requestID), + ) + return nil + } + + // This node timed out their request, so we can add them back to [fetchFrom] + t.fetchFrom.Add(nodeID) + + // Send another request for this + return t.fetch(ctx, blkID) +} + +// Get block [blkID] and its ancestors from a peer +func (t *Transitive) fetch(ctx context.Context, blkID ids.ID) error { + // Make sure we haven't already requested this block + if t.backfillingRequests.Contains(blkID) { + return nil + } - // We only allow one outbound request at a time from a node - t.markUnavailable(validatorID) - t.RequestID++ - t.Sender.SendGetAncestors(ctx, validatorID, t.RequestID, blkID) + if _, err := t.VM.GetBlock(ctx, blkID); err == nil { + // Requesting known block is the stopping condition for block backfilling return nil } + + validatorID, ok := t.fetchFrom.Peek() + if !ok { + return fmt.Errorf("dropping request for %s as there are no peers", blkID) + } + + // We only allow one outbound request at a time from a node + t.markUnavailable(validatorID) + t.RequestID++ + t.backfillingRequests.Add(validatorID, t.RequestID, blkID) + t.Sender.SendGetAncestors(ctx, validatorID, t.RequestID, blkID) + return nil } func (t *Transitive) markUnavailable(nodeID ids.NodeID) { @@ -1050,10 +1134,10 @@ func (t *Transitive) Connected(ctx context.Context, nodeID ids.NodeID, nodeVersi if _, ok := t.Validators.GetValidator(t.Ctx.SubnetID, nodeID); ok { t.fetchFrom.Add(nodeID) } - return t.Connector.Connected(ctx, nodeID, nodeVersion) + return t.VM.Connected(ctx, nodeID, nodeVersion) } func (t *Transitive) Disconnected(ctx context.Context, nodeID ids.NodeID) error { t.markUnavailable(nodeID) - return t.Connector.Disconnected(ctx, nodeID) + return t.VM.Disconnected(ctx, nodeID) } From 1b7015ef4ebd2327518c617efe2b11bc36b0a783 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 30 Oct 2023 11:20:08 +0100 Subject: [PATCH 09/36] improved StateSyncableVM interface --- proto/pb/vm/vm.pb.go | 17 +++++++++++---- proto/vm/vm.proto | 3 ++- .../snowman/block/mocks/state_syncable_vm.go | 7 ++++--- .../engine/snowman/block/state_syncable_vm.go | 21 +++++++++++-------- .../snowman/block/test_state_syncable_vm.go | 6 +++--- vms/metervm/state_syncable_vm.go | 10 ++++----- vms/proposervm/state_syncable_vm.go | 6 +++--- vms/rpcchainvm/vm_client.go | 8 +++---- vms/rpcchainvm/vm_server.go | 8 +++++-- vms/tracedvm/state_syncable_vm.go | 4 ++-- 10 files changed, 54 insertions(+), 36 deletions(-) diff --git a/proto/pb/vm/vm.pb.go b/proto/pb/vm/vm.pb.go index 09c99e307172..187b8e34b816 100644 --- a/proto/pb/vm/vm.pb.go +++ b/proto/pb/vm/vm.pb.go @@ -3042,7 +3042,8 @@ type BackfillBlocksResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Err Error `protobuf:"varint,1,opt,name=err,proto3,enum=vm.Error" json:"err,omitempty"` + Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Err Error `protobuf:"varint,2,opt,name=err,proto3,enum=vm.Error" json:"err,omitempty"` } func (x *BackfillBlocksResponse) Reset() { @@ -3077,6 +3078,13 @@ func (*BackfillBlocksResponse) Descriptor() ([]byte, []int) { return file_vm_vm_proto_rawDescGZIP(), []int{47} } +func (x *BackfillBlocksResponse) GetId() []byte { + if x != nil { + return x.Id + } + return nil +} + func (x *BackfillBlocksResponse) GetErr() Error { if x != nil { return x.Err @@ -3500,9 +3508,10 @@ var file_vm_vm_proto_rawDesc = []byte{ 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6b, 0x73, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x62, 0x6c, 0x6b, 0x73, 0x42, 0x79, 0x74, - 0x65, 0x73, 0x22, 0x35, 0x0a, 0x16, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x03, - 0x65, 0x72, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, 0x6d, 0x2e, 0x45, + 0x65, 0x73, 0x22, 0x45, 0x0a, 0x16, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x73, 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, 0x1b, 0x0a, 0x03, + 0x65, 0x72, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, 0x6d, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0x31, 0x0a, 0x19, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, diff --git a/proto/vm/vm.proto b/proto/vm/vm.proto index 5daef45cbcc7..fb795777e7e7 100644 --- a/proto/vm/vm.proto +++ b/proto/vm/vm.proto @@ -410,7 +410,8 @@ message BackfillBlocksRequest { } message BackfillBlocksResponse { - Error err = 1; + bytes id = 1; + Error err = 2; } message StateSummaryAcceptRequest { diff --git a/snow/engine/snowman/block/mocks/state_syncable_vm.go b/snow/engine/snowman/block/mocks/state_syncable_vm.go index 247afd11d355..64470a599656 100644 --- a/snow/engine/snowman/block/mocks/state_syncable_vm.go +++ b/snow/engine/snowman/block/mocks/state_syncable_vm.go @@ -40,11 +40,12 @@ func (m *MockStateSyncableVM) EXPECT() *MockStateSyncableVMMockRecorder { } // BackfillBlocks mocks base method. -func (m *MockStateSyncableVM) BackfillBlocks(arg0 context.Context, arg1 [][]byte) error { +func (m *MockStateSyncableVM) BackfillBlocks(arg0 context.Context, arg1 [][]byte) (ids.ID, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "BackfillBlocks", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 + ret0, _ := ret[0].(ids.ID) + ret1, _ := ret[1].(error) + return ret0, ret1 } // BackfillBlocks indicates an expected call of BackfillBlocks. diff --git a/snow/engine/snowman/block/state_syncable_vm.go b/snow/engine/snowman/block/state_syncable_vm.go index c8868c07d598..7b570bb979aa 100644 --- a/snow/engine/snowman/block/state_syncable_vm.go +++ b/snow/engine/snowman/block/state_syncable_vm.go @@ -10,7 +10,11 @@ import ( "github.com/ava-labs/avalanchego/ids" ) -var ErrStateSyncableVMNotImplemented = errors.New("vm does not implement StateSyncableVM interface") +var ( + ErrStateSyncableVMNotImplemented = errors.New("vm does not implement StateSyncableVM interface") + ErrBlockBackfillingNotEnabled = errors.New("vm does not require block backfilling") + ErrStopBlockBackfilling = errors.New("vm required stopping block backfilling") +) // StateSyncableVM contains the functionality to allow VMs to sync to a given // state, rather then boostrapping from genesis. @@ -48,16 +52,15 @@ type StateSyncableVM interface { // BackfillBlocksEnabled checks if VM wants to download all blocks from state summary one // down to genesis. // - // Returns ids.EmptyID if block backfilling is not enabled. - // TODO ABENEGIA: Use error instead of the EmptyID + // Returns ErrBlockBackfillingNotEnabled if block backfilling is not enabled. BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) - // BackfillBlocks pass blocks bytes retrieved via GetAncestors calls to the VM - // It's left to the VM the duty to parse and validate the blocks. + // BackfillBlocks passes blocks bytes retrieved via GetAncestors calls to the VM + // It's left to the VM the to parse, validate and index the blocks. // BackfillBlocks returns the next block ID to be requested and an error - // Upon error, engine will issue a GetAncestor call to a different peer + // If BackfillBlocks returns no error, engine will request the blockID returned by the VM + // If BackfillBlocks returns ErrStopBlockBackfilling, engine will stop requesting block ancestors + // If BackfillBlocks returns any other error, engine will issue a GetAncestor call to a different peer // with the previously requested block ID - // If BackfillBlocks returns a block known to the VM, the engine will - // stop asking for blocks ancestors. (TODO: consider using a boolean or an empty blockID) - BackfillBlocks(ctx context.Context, blocks [][]byte) error + BackfillBlocks(ctx context.Context, blocks [][]byte) (ids.ID, error) } diff --git a/snow/engine/snowman/block/test_state_syncable_vm.go b/snow/engine/snowman/block/test_state_syncable_vm.go index e67581bcbd99..913989c7853e 100644 --- a/snow/engine/snowman/block/test_state_syncable_vm.go +++ b/snow/engine/snowman/block/test_state_syncable_vm.go @@ -41,7 +41,7 @@ type TestStateSyncableVM struct { GetStateSummaryF func(ctx context.Context, summaryHeight uint64) (StateSummary, error) BackfillBlocksEnabledF func(context.Context) (ids.ID, error) - BackfillBlocksF func(context.Context, [][]byte) error + BackfillBlocksF func(context.Context, [][]byte) (ids.ID, error) } func (vm *TestStateSyncableVM) StateSyncEnabled(ctx context.Context) (bool, error) { @@ -104,12 +104,12 @@ func (vm *TestStateSyncableVM) BackfillBlocksEnabled(ctx context.Context) (ids.I return ids.Empty, errBackfillBlocksEnabled } -func (vm *TestStateSyncableVM) BackfillBlocks(ctx context.Context, blocks [][]byte) error { +func (vm *TestStateSyncableVM) BackfillBlocks(ctx context.Context, blocks [][]byte) (ids.ID, error) { if vm.BackfillBlocksF != nil { return vm.BackfillBlocksF(ctx, blocks) } if vm.CantGetStateSummary && vm.T != nil { require.FailNow(vm.T, errGetStateSummary.Error()) } - return errBackfillBlock + return ids.Empty, errBackfillBlock } diff --git a/vms/metervm/state_syncable_vm.go b/vms/metervm/state_syncable_vm.go index 6b37f29510fc..092942f5b61a 100644 --- a/vms/metervm/state_syncable_vm.go +++ b/vms/metervm/state_syncable_vm.go @@ -97,19 +97,19 @@ func (vm *blockVM) BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) { return blkID, nil } -func (vm *blockVM) BackfillBlocks(ctx context.Context, blocks [][]byte) error { +func (vm *blockVM) BackfillBlocks(ctx context.Context, blocks [][]byte) (ids.ID, error) { if vm.ssVM == nil { - return block.ErrStateSyncableVMNotImplemented + return ids.Empty, block.ErrStateSyncableVMNotImplemented } start := vm.clock.Time() - err := vm.ssVM.BackfillBlocks(ctx, blocks) + nextWantedBlkID, err := vm.ssVM.BackfillBlocks(ctx, blocks) end := vm.clock.Time() duration := float64(end.Sub(start)) if err != nil { vm.blockMetrics.backfillBlocks.Observe(duration) - return err + return nextWantedBlkID, err } vm.blockMetrics.backfillBlocks.Observe(duration) - return nil + return nextWantedBlkID, nil } diff --git a/vms/proposervm/state_syncable_vm.go b/vms/proposervm/state_syncable_vm.go index 7221ea9e0e04..270b0f7b5788 100644 --- a/vms/proposervm/state_syncable_vm.go +++ b/vms/proposervm/state_syncable_vm.go @@ -169,17 +169,17 @@ func (vm *VM) BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) { return vm.ssVM.BackfillBlocksEnabled(ctx) } -func (vm *VM) BackfillBlocks(ctx context.Context, blksBytes [][]byte) error { +func (vm *VM) BackfillBlocks(ctx context.Context, blksBytes [][]byte) (ids.ID, error) { innerBlksBytes := make([][]byte, 0, len(blksBytes)) for i, blkBytes := range blksBytes { blk, err := vm.parseProposerBlock(ctx, blkBytes) if err != nil { - return fmt.Errorf("failed parsing backfilled block, index %d, %w", i, err) + return ids.Empty, fmt.Errorf("failed parsing backfilled block, index %d, %w", i, err) } // TODO: consider validating that block is at least below last accepted block // or that block has not been stored yet if err := blk.acceptOuterBlk(); err != nil { - return err + return ids.Empty, fmt.Errorf("failed indexing backfilled block, index %d, %w", i, err) } innerBlksBytes = append(innerBlksBytes, blk.getInnerBlk().Bytes()) } diff --git a/vms/rpcchainvm/vm_client.go b/vms/rpcchainvm/vm_client.go index 0fc65f5bd6a3..c921fe09a62b 100644 --- a/vms/rpcchainvm/vm_client.go +++ b/vms/rpcchainvm/vm_client.go @@ -827,7 +827,7 @@ func (vm *VMClient) BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) { return ids.ID(resp.Id), err } -func (vm *VMClient) BackfillBlocks(ctx context.Context, blocks [][]byte) error { +func (vm *VMClient) BackfillBlocks(ctx context.Context, blocks [][]byte) (ids.ID, error) { resp, err := vm.client.BackfillBlocks( ctx, &vmpb.BackfillBlocksRequest{ @@ -835,12 +835,12 @@ func (vm *VMClient) BackfillBlocks(ctx context.Context, blocks [][]byte) error { }, ) if err != nil { - return err + return ids.Empty, err } if errEnum := resp.Err; errEnum != vmpb.Error_ERROR_UNSPECIFIED { - return errEnumToError[errEnum] + return ids.ID(resp.Id), errEnumToError[errEnum] } - return nil + return ids.ID(resp.Id), nil } func (vm *VMClient) newBlockFromBuildBlock(resp *vmpb.BuildBlockResponse) (*blockClient, error) { diff --git a/vms/rpcchainvm/vm_server.go b/vms/rpcchainvm/vm_server.go index d40c5cf84245..94f9185b427f 100644 --- a/vms/rpcchainvm/vm_server.go +++ b/vms/rpcchainvm/vm_server.go @@ -837,12 +837,16 @@ func (vm *VMServer) BackfillBlocksEnabled(ctx context.Context, _ *emptypb.Empty) } func (vm *VMServer) BackfillBlocks(ctx context.Context, req *vmpb.BackfillBlocksRequest) (*vmpb.BackfillBlocksResponse, error) { - var err error + var ( + nextWantedBlkID ids.ID + err error + ) if vm.ssVM != nil { - err = vm.ssVM.BackfillBlocks(ctx, req.BlksBytes) + nextWantedBlkID, err = vm.ssVM.BackfillBlocks(ctx, req.BlksBytes) } return &vmpb.BackfillBlocksResponse{ + Id: nextWantedBlkID[:], Err: errorToErrEnum[err], }, errorToRPCError(err) } diff --git a/vms/tracedvm/state_syncable_vm.go b/vms/tracedvm/state_syncable_vm.go index e9f6f98bb019..c474d3c4960b 100644 --- a/vms/tracedvm/state_syncable_vm.go +++ b/vms/tracedvm/state_syncable_vm.go @@ -84,9 +84,9 @@ func (vm *blockVM) BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) { return vm.ssVM.BackfillBlocksEnabled(ctx) } -func (vm *blockVM) BackfillBlocks(ctx context.Context, blocks [][]byte) error { +func (vm *blockVM) BackfillBlocks(ctx context.Context, blocks [][]byte) (ids.ID, error) { if vm.ssVM == nil { - return block.ErrStateSyncableVMNotImplemented + return ids.Empty, block.ErrStateSyncableVMNotImplemented } ctx, span := vm.tracer.Start(ctx, vm.backfillBlocksTag, oteltrace.WithAttributes( From 36905ac6589d2fa4ddc3b8d4ee33a84104bb0e76 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 30 Oct 2023 11:34:22 +0100 Subject: [PATCH 10/36] temporarily cut coreth dependency --- go.mod | 25 - go.sum | 76 -- node/node.go | 4 +- tests/e2e/c/dynamic_fees.go | 328 ++++---- tests/e2e/c/interchain_workflow.go | 322 +++---- tests/e2e/e2e.go | 124 +-- tests/e2e/p/interchain_workflow.go | 446 +++++----- tests/e2e/x/interchain_workflow.go | 298 +++---- tests/fixture/testnet/config.go | 56 +- vms/example/xsvm/cmd/chain/create/cmd.go | 6 +- wallet/chain/c/backend.go | 300 +++---- wallet/chain/c/builder.go | 792 +++++++++--------- wallet/chain/c/builder_with_options.go | 136 +-- wallet/chain/c/context.go | 130 +-- wallet/chain/c/signer.go | 436 +++++----- wallet/chain/c/wallet.go | 402 ++++----- wallet/chain/c/wallet_with_options.go | 134 +-- wallet/subnet/primary/api.go | 123 +-- wallet/subnet/primary/example_test.go | 2 +- .../add-permissioned-subnet-validator/main.go | 6 +- .../examples/add-primary-validator/main.go | 2 +- .../primary/examples/c-chain-export/main.go | 118 +-- .../primary/examples/c-chain-import/main.go | 126 +-- .../primary/examples/create-asset/main.go | 2 +- .../primary/examples/create-chain/main.go | 6 +- .../examples/create-locked-stakeable/main.go | 2 +- .../primary/examples/create-subnet/main.go | 2 +- .../examples/remove-subnet-validator/main.go | 6 +- wallet/subnet/primary/wallet.go | 43 +- 29 files changed, 2178 insertions(+), 2275 deletions(-) diff --git a/go.mod b/go.mod index ae9ea2a12051..40d59d0cb294 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,6 @@ require ( github.com/DataDog/zstd v1.5.2 github.com/Microsoft/go-winio v0.5.2 github.com/NYTimes/gziphandler v1.1.1 - github.com/ava-labs/coreth v0.12.7-0.20231026130315-648dfa6abecd github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 github.com/btcsuite/btcd/btcutil v1.1.3 github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 @@ -72,7 +71,6 @@ require ( require ( github.com/BurntSushi/toml v1.2.1 // indirect - github.com/VictoriaMetrics/fastcache v1.10.0 // indirect github.com/benbjohnson/clock v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect @@ -81,44 +79,26 @@ require ( github.com/cockroachdb/errors v1.9.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/redact v1.1.3 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/deckarep/golang-set/v2 v2.1.0 // indirect - github.com/dlclark/regexp2 v1.7.0 // indirect - github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect - github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/frankban/quicktest v1.14.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect - github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect - github.com/go-stack/stack v1.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect - github.com/google/uuid v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 // indirect - github.com/hashicorp/go-bexpr v0.1.10 // indirect - github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/klauspost/compress v1.15.15 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/magiconair/properties v1.8.6 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/mitchellh/pointerstructure v1.2.0 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect @@ -126,17 +106,12 @@ require ( github.com/prometheus/common v0.39.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sanity-io/litter v1.5.1 // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/status-im/keycard-go v0.2.0 // indirect github.com/subosito/gotenv v1.3.0 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect - github.com/tyler-smith/go-bip39 v1.1.0 // indirect - github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa // indirect - github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/zondax/hid v0.9.1 // indirect github.com/zondax/ledger-go v0.14.1 // indirect diff --git a/go.sum b/go.sum index c027a0a85867..09e5526b3f20 100644 --- a/go.sum +++ b/go.sum @@ -52,18 +52,12 @@ github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cq github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= -github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY= -github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/ava-labs/coreth v0.12.7-0.20231026130315-648dfa6abecd h1:Kgh+NpQ5VaiQpX8NJ32HqbYPVqA8vo3zG3v7JKLFs1A= -github.com/ava-labs/coreth v0.12.7-0.20231026130315-648dfa6abecd/go.mod h1:EsxxCWSBxMMZtgd62AS5ZtmGujZEFPp2EFq4JJCcJ8k= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 h1:EdxD90j5sClfL5Ngpz2TlnbnkNYdFPDXa0jDOjam65c= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7/go.mod h1:XhiXSrh90sHUbkERzaxEftCmUz53eCijshDLZ4fByVM= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= @@ -100,18 +94,13 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -141,16 +130,12 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= -github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= @@ -161,14 +146,6 @@ github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6ps github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= -github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= -github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= -github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= -github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -185,8 +162,6 @@ github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2 github.com/ethereum/go-ethereum v1.12.0/go.mod h1:/oo2X/dZLJjf2mJ6YT9wcWxa4nNJDBKDBU6sFIpx1Gs= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -195,8 +170,6 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= @@ -220,11 +193,7 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= -github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= @@ -309,14 +278,10 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -337,17 +302,11 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 h1:kr3j8iIMR4ywO/O0rvksXaJvauGGCMg2zAZIiNZ9uIQ= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0/go.mod h1:ummNFgdgLhhX7aIiy35vVmQNS0rWXknfPE0qe6fmFXg= -github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= -github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e/go.mod h1:j9cQbcqHQujT0oKJ38PylVfqohClLr3CvDC+Qcg+lhU= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8= @@ -359,7 +318,6 @@ github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3 github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -401,7 +359,6 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -409,7 +366,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= @@ -420,17 +376,11 @@ github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -439,11 +389,8 @@ github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= -github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -462,8 +409,6 @@ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -531,8 +476,6 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sanity-io/litter v1.5.1 h1:dwnrSypP6q56o3lFxTU+t2fwQ9A+U5qrXVO4Qg9KwVU= github.com/sanity-io/litter v1.5.1/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0= @@ -568,8 +511,6 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= -github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= -github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -599,14 +540,10 @@ github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITn github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= -github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -618,8 +555,6 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1: github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= @@ -629,7 +564,6 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= @@ -727,7 +661,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -773,7 +706,6 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -797,7 +729,6 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -862,12 +793,8 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -884,7 +811,6 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -948,7 +874,6 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1073,7 +998,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= diff --git a/node/node.go b/node/node.go index 4200a33699ab..9e72b7dcc450 100644 --- a/node/node.go +++ b/node/node.go @@ -24,7 +24,7 @@ import ( "go.uber.org/zap" - coreth "github.com/ava-labs/coreth/plugin/evm" + // coreth "github.com/ava-labs/coreth/plugin/evm" "github.com/ava-labs/avalanchego/api/admin" "github.com/ava-labs/avalanchego/api/auth" @@ -935,7 +935,7 @@ func (n *Node) initVMs() error { CreateAssetTxFee: n.Config.CreateAssetTxFee, }, }), - vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), + // vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), n.VMManager.RegisterFactory(context.TODO(), secp256k1fx.ID, &secp256k1fx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), nftfx.ID, &nftfx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), propertyfx.ID, &propertyfx.Factory{}), diff --git a/tests/e2e/c/dynamic_fees.go b/tests/e2e/c/dynamic_fees.go index f3a1daaf3d2c..4234c170af6f 100644 --- a/tests/e2e/c/dynamic_fees.go +++ b/tests/e2e/c/dynamic_fees.go @@ -3,167 +3,167 @@ package c -import ( - "math/big" - "strings" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/stretchr/testify/require" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/coreth/core/types" - "github.com/ava-labs/coreth/params" - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/tests" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/tests/fixture/testnet" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -) - -// This test uses the compiled bin for `hashing.sol` as -// well as its ABI contained in `hashing_contract.go`. - -var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { - require := require.New(ginkgo.GinkgoT()) - - // Need a gas limit much larger than the standard 21_000 to enable - // the contract to induce a gas price increase - const largeGasLimit = uint64(8_000_000) - - // TODO(marun) What is the significance of this value? - gasTip := big.NewInt(1000 * params.GWei) - - ginkgo.It("should ensure that the gas price is affected by load", func() { - ginkgo.By("creating a new private network to ensure isolation from other tests") - privateNetwork := e2e.Env.NewPrivateNetwork() - - ginkgo.By("allocating a pre-funded key") - key := privateNetwork.GetConfig().FundedKeys[0] - ethAddress := evm.GetEthAddress(key) - - ginkgo.By("initializing a coreth client") - node := privateNetwork.GetNodes()[0] - nodeURI := testnet.NodeURI{ - NodeID: node.GetID(), - URI: node.GetProcessContext().URI, - } - ethClient := e2e.Env.NewEthClient(nodeURI) - - ginkgo.By("initializing a transaction signer") - cChainID, err := ethClient.ChainID(e2e.DefaultContext()) - require.NoError(err) - signer := types.NewEIP155Signer(cChainID) - ecdsaKey := key.ToECDSA() - sign := func(tx *types.Transaction) *types.Transaction { - signedTx, err := types.SignTx(tx, signer, ecdsaKey) - require.NoError(err) - return signedTx - } - - var contractAddress common.Address - ginkgo.By("deploying an expensive contract", func() { - // Create transaction - nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) - require.NoError(err) - compiledContract := common.Hex2Bytes(hashingCompiledContract) - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - GasPrice: gasTip, - Gas: largeGasLimit, - Value: common.Big0, - Data: compiledContract, - }) - - // Send the transaction and wait for acceptance - signedTx := sign(tx) - receipt := e2e.SendEthTransaction(ethClient, signedTx) - - contractAddress = receipt.ContractAddress - }) - - var gasPrice *big.Int - ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { - // Evaluate the bytes representation of the contract - hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) - require.NoError(err) - contractData, err := hashingABI.Pack("hashIt") - require.NoError(err) - - var initialGasPrice *big.Int - e2e.Eventually(func() bool { - // Check the gas price - var err error - gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) - require.NoError(err) - if initialGasPrice == nil { - initialGasPrice = gasPrice - tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) - } else if gasPrice.Cmp(initialGasPrice) > 0 { - // Gas price has increased - tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) - return true - } - - // Create the transaction - nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) - require.NoError(err) - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - GasPrice: gasTip, - Gas: largeGasLimit, - To: &contractAddress, - Value: common.Big0, - Data: contractData, - }) - - // Send the transaction and wait for acceptance - signedTx := sign(tx) - _ = e2e.SendEthTransaction(ethClient, signedTx) - - // The gas price will be checked at the start of the next iteration - return false - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") - }) - - ginkgo.By("waiting for the gas price to decrease...", func() { - initialGasPrice := gasPrice - e2e.Eventually(func() bool { - var err error - gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) - require.NoError(err) - tests.Outf("{{blue}}.{{/}}") - return initialGasPrice.Cmp(gasPrice) > 0 - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") - tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) - }) - - ginkgo.By("sending funds at the current gas price", func() { - // Create a recipient address - factory := secp256k1.Factory{} - recipientKey, err := factory.NewPrivateKey() - require.NoError(err) - recipientEthAddress := evm.GetEthAddress(recipientKey) - - // Create transaction - nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) - require.NoError(err) - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - GasPrice: gasPrice, - Gas: e2e.DefaultGasLimit, - To: &recipientEthAddress, - Value: common.Big0, - }) - - // Send the transaction and wait for acceptance - signedTx := sign(tx) - _ = e2e.SendEthTransaction(ethClient, signedTx) - }) - - e2e.CheckBootstrapIsPossible(privateNetwork) - }) -}) +// import ( +// "math/big" +// "strings" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/stretchr/testify/require" + +// "github.com/ethereum/go-ethereum/accounts/abi" +// "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/coreth/core/types" +// "github.com/ava-labs/coreth/params" +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/tests" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/tests/fixture/testnet" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// ) + +// // This test uses the compiled bin for `hashing.sol` as +// // well as its ABI contained in `hashing_contract.go`. + +// var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { +// require := require.New(ginkgo.GinkgoT()) + +// // Need a gas limit much larger than the standard 21_000 to enable +// // the contract to induce a gas price increase +// const largeGasLimit = uint64(8_000_000) + +// // TODO(marun) What is the significance of this value? +// gasTip := big.NewInt(1000 * params.GWei) + +// ginkgo.It("should ensure that the gas price is affected by load", func() { +// ginkgo.By("creating a new private network to ensure isolation from other tests") +// privateNetwork := e2e.Env.NewPrivateNetwork() + +// ginkgo.By("allocating a pre-funded key") +// key := privateNetwork.GetConfig().FundedKeys[0] +// ethAddress := evm.GetEthAddress(key) + +// ginkgo.By("initializing a coreth client") +// node := privateNetwork.GetNodes()[0] +// nodeURI := testnet.NodeURI{ +// NodeID: node.GetID(), +// URI: node.GetProcessContext().URI, +// } +// ethClient := e2e.Env.NewEthClient(nodeURI) + +// ginkgo.By("initializing a transaction signer") +// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) +// require.NoError(err) +// signer := types.NewEIP155Signer(cChainID) +// ecdsaKey := key.ToECDSA() +// sign := func(tx *types.Transaction) *types.Transaction { +// signedTx, err := types.SignTx(tx, signer, ecdsaKey) +// require.NoError(err) +// return signedTx +// } + +// var contractAddress common.Address +// ginkgo.By("deploying an expensive contract", func() { +// // Create transaction +// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) +// require.NoError(err) +// compiledContract := common.Hex2Bytes(hashingCompiledContract) +// tx := types.NewTx(&types.LegacyTx{ +// Nonce: nonce, +// GasPrice: gasTip, +// Gas: largeGasLimit, +// Value: common.Big0, +// Data: compiledContract, +// }) + +// // Send the transaction and wait for acceptance +// signedTx := sign(tx) +// receipt := e2e.SendEthTransaction(ethClient, signedTx) + +// contractAddress = receipt.ContractAddress +// }) + +// var gasPrice *big.Int +// ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { +// // Evaluate the bytes representation of the contract +// hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) +// require.NoError(err) +// contractData, err := hashingABI.Pack("hashIt") +// require.NoError(err) + +// var initialGasPrice *big.Int +// e2e.Eventually(func() bool { +// // Check the gas price +// var err error +// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) +// require.NoError(err) +// if initialGasPrice == nil { +// initialGasPrice = gasPrice +// tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) +// } else if gasPrice.Cmp(initialGasPrice) > 0 { +// // Gas price has increased +// tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) +// return true +// } + +// // Create the transaction +// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) +// require.NoError(err) +// tx := types.NewTx(&types.LegacyTx{ +// Nonce: nonce, +// GasPrice: gasTip, +// Gas: largeGasLimit, +// To: &contractAddress, +// Value: common.Big0, +// Data: contractData, +// }) + +// // Send the transaction and wait for acceptance +// signedTx := sign(tx) +// _ = e2e.SendEthTransaction(ethClient, signedTx) + +// // The gas price will be checked at the start of the next iteration +// return false +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") +// }) + +// ginkgo.By("waiting for the gas price to decrease...", func() { +// initialGasPrice := gasPrice +// e2e.Eventually(func() bool { +// var err error +// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) +// require.NoError(err) +// tests.Outf("{{blue}}.{{/}}") +// return initialGasPrice.Cmp(gasPrice) > 0 +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") +// tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) +// }) + +// ginkgo.By("sending funds at the current gas price", func() { +// // Create a recipient address +// factory := secp256k1.Factory{} +// recipientKey, err := factory.NewPrivateKey() +// require.NoError(err) +// recipientEthAddress := evm.GetEthAddress(recipientKey) + +// // Create transaction +// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) +// require.NoError(err) +// tx := types.NewTx(&types.LegacyTx{ +// Nonce: nonce, +// GasPrice: gasPrice, +// Gas: e2e.DefaultGasLimit, +// To: &recipientEthAddress, +// Value: common.Big0, +// }) + +// // Send the transaction and wait for acceptance +// signedTx := sign(tx) +// _ = e2e.SendEthTransaction(ethClient, signedTx) +// }) + +// e2e.CheckBootstrapIsPossible(privateNetwork) +// }) +// }) diff --git a/tests/e2e/c/interchain_workflow.go b/tests/e2e/c/interchain_workflow.go index 47c430d4c12a..a072596e1dc9 100644 --- a/tests/e2e/c/interchain_workflow.go +++ b/tests/e2e/c/interchain_workflow.go @@ -3,164 +3,164 @@ package c -import ( - "math/big" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/coreth/core/types" - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { - require := require.New(ginkgo.GinkgoT()) - - const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer - - ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { - ginkgo.By("initializing a new eth client") - // Select a random node URI to use for both the eth client and - // the wallet to avoid having to verify that all nodes are at - // the same height before initializing the wallet. - nodeURI := e2e.Env.GetRandomNodeURI() - ethClient := e2e.Env.NewEthClient(nodeURI) - - ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") - senderKey := e2e.Env.AllocateFundedKey() - senderEthAddress := evm.GetEthAddress(senderKey) - factory := secp256k1.Factory{} - recipientKey, err := factory.NewPrivateKey() - require.NoError(err) - recipientEthAddress := evm.GetEthAddress(recipientKey) - - ginkgo.By("sending funds from one address to another on the C-Chain", func() { - // Create transaction - acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) - require.NoError(err) - gasPrice := e2e.SuggestGasPrice(ethClient) - tx := types.NewTransaction( - acceptedNonce, - recipientEthAddress, - big.NewInt(int64(txAmount)), - e2e.DefaultGasLimit, - gasPrice, - nil, - ) - - // Sign transaction - cChainID, err := ethClient.ChainID(e2e.DefaultContext()) - require.NoError(err) - signer := types.NewEIP155Signer(cChainID) - signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) - require.NoError(err) - - _ = e2e.SendEthTransaction(ethClient, signedTx) - - ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") - e2e.Eventually(func() bool { - balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) - require.NoError(err) - return balance.Cmp(big.NewInt(0)) > 0 - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") - }) - - // Wallet must be initialized after sending funds on the - // C-Chain with the same node URI to ensure wallet state - // matches on-chain state. - ginkgo.By("initializing a keychain and associated wallet") - keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) - baseWallet := e2e.Env.NewWallet(keychain, nodeURI) - xWallet := baseWallet.X() - cWallet := baseWallet.C() - pWallet := baseWallet.P() - - ginkgo.By("defining common configuration") - avaxAssetID := xWallet.AVAXAssetID() - // Use the same owner for import funds to X-Chain and P-Chain - recipientOwner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - recipientKey.Address(), - }, - } - // Use the same outputs for both X-Chain and P-Chain exports - exportOutputs := []*secp256k1fx.TransferOutput{ - { - Amt: txAmount, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - keychain.Keys[0].Address(), - }, - }, - }, - } - - ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { - _, err := cWallet.IssueExportTx( - xWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { - _, err := xWallet.IssueImportTx( - cWallet.BlockchainID(), - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { - balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { - _, err := cWallet.IssueExportTx( - constants.PlatformChainID, - exportOutputs, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { - _, err = pWallet.IssueImportTx( - cWallet.BlockchainID(), - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { - balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) - }) -}) +// import ( +// "math/big" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/stretchr/testify/require" + +// "github.com/ava-labs/coreth/core/types" +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { +// require := require.New(ginkgo.GinkgoT()) + +// const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer + +// ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { +// ginkgo.By("initializing a new eth client") +// // Select a random node URI to use for both the eth client and +// // the wallet to avoid having to verify that all nodes are at +// // the same height before initializing the wallet. +// nodeURI := e2e.Env.GetRandomNodeURI() +// ethClient := e2e.Env.NewEthClient(nodeURI) + +// ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") +// senderKey := e2e.Env.AllocateFundedKey() +// senderEthAddress := evm.GetEthAddress(senderKey) +// factory := secp256k1.Factory{} +// recipientKey, err := factory.NewPrivateKey() +// require.NoError(err) +// recipientEthAddress := evm.GetEthAddress(recipientKey) + +// ginkgo.By("sending funds from one address to another on the C-Chain", func() { +// // Create transaction +// acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) +// require.NoError(err) +// gasPrice := e2e.SuggestGasPrice(ethClient) +// tx := types.NewTransaction( +// acceptedNonce, +// recipientEthAddress, +// big.NewInt(int64(txAmount)), +// e2e.DefaultGasLimit, +// gasPrice, +// nil, +// ) + +// // Sign transaction +// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) +// require.NoError(err) +// signer := types.NewEIP155Signer(cChainID) +// signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) +// require.NoError(err) + +// _ = e2e.SendEthTransaction(ethClient, signedTx) + +// ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") +// e2e.Eventually(func() bool { +// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) +// require.NoError(err) +// return balance.Cmp(big.NewInt(0)) > 0 +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") +// }) + +// // Wallet must be initialized after sending funds on the +// // C-Chain with the same node URI to ensure wallet state +// // matches on-chain state. +// ginkgo.By("initializing a keychain and associated wallet") +// keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) +// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) +// xWallet := baseWallet.X() +// cWallet := baseWallet.C() +// pWallet := baseWallet.P() + +// ginkgo.By("defining common configuration") +// avaxAssetID := xWallet.AVAXAssetID() +// // Use the same owner for import funds to X-Chain and P-Chain +// recipientOwner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// recipientKey.Address(), +// }, +// } +// // Use the same outputs for both X-Chain and P-Chain exports +// exportOutputs := []*secp256k1fx.TransferOutput{ +// { +// Amt: txAmount, +// OutputOwners: secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// keychain.Keys[0].Address(), +// }, +// }, +// }, +// } + +// ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { +// _, err := cWallet.IssueExportTx( +// xWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { +// _, err := xWallet.IssueImportTx( +// cWallet.BlockchainID(), +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { +// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { +// _, err := cWallet.IssueExportTx( +// constants.PlatformChainID, +// exportOutputs, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { +// _, err = pWallet.IssueImportTx( +// cWallet.BlockchainID(), +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { +// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) +// }) +// }) diff --git a/tests/e2e/e2e.go b/tests/e2e/e2e.go index 130f33f1197c..790748b705b1 100644 --- a/tests/e2e/e2e.go +++ b/tests/e2e/e2e.go @@ -7,22 +7,24 @@ package e2e import ( "context" "encoding/json" - "errors" - "fmt" - "math/big" + + // "errors" + // "fmt" + // "math/big" "math/rand" "os" "path/filepath" - "strings" + + // "strings" "time" ginkgo "github.com/onsi/ginkgo/v2" "github.com/stretchr/testify/require" - "github.com/ava-labs/coreth/core/types" - "github.com/ava-labs/coreth/ethclient" - "github.com/ava-labs/coreth/interfaces" + // "github.com/ava-labs/coreth/core/types" + // "github.com/ava-labs/coreth/ethclient" + // "github.com/ava-labs/coreth/interfaces" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/tests" @@ -134,7 +136,7 @@ func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain, nodeURI tes baseWallet, err := primary.MakeWallet(DefaultContext(), &primary.WalletConfig{ URI: nodeURI.URI, AVAXKeychain: keychain, - EthKeychain: keychain, + // EthKeychain: keychain, }) te.require.NoError(err) return primary.NewWalletWithOptions( @@ -147,16 +149,16 @@ func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain, nodeURI tes ) } -// Create a new eth client targeting the specified node URI. -// TODO(marun) Make this a regular function. -func (te *TestEnvironment) NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { - tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) - nodeAddress := strings.Split(nodeURI.URI, "//")[1] - uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) - client, err := ethclient.Dial(uri) - te.require.NoError(err) - return client -} +// // Create a new eth client targeting the specified node URI. +// // TODO(marun) Make this a regular function. +// func (te *TestEnvironment) NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { +// tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) +// nodeAddress := strings.Split(nodeURI.URI, "//")[1] +// uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) +// client, err := ethclient.Dial(uri) +// te.require.NoError(err) +// return client +// } // Create a new private network that is not shared with other tests. func (te *TestEnvironment) NewPrivateNetwork() testnet.Network { @@ -231,49 +233,49 @@ func WaitForHealthy(node testnet.Node) { require.NoError(ginkgo.GinkgoT(), testnet.WaitForHealthy(DefaultContext(), node)) } -// Sends an eth transaction, waits for the transaction receipt to be issued -// and checks that the receipt indicates success. -func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { - require := require.New(ginkgo.GinkgoT()) - - txID := signedTx.Hash() - tests.Outf(" sending eth transaction with ID: %s\n", txID) - - require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) - - // Wait for the receipt - var receipt *types.Receipt - Eventually(func() bool { - var err error - receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) - if errors.Is(err, interfaces.NotFound) { - return false // Transaction is still pending - } - require.NoError(err) - return true - }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") - - require.Equal(receipt.Status, types.ReceiptStatusSuccessful) - return receipt -} - -// Determines the suggested gas price for the configured client that will -// maximize the chances of transaction acceptance. -func SuggestGasPrice(ethClient ethclient.Client) *big.Int { - gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) - require.NoError(ginkgo.GinkgoT(), err) - // Double the suggested gas price to maximize the chances of - // acceptance. Maybe this can be revisited pending resolution of - // https://github.com/ava-labs/coreth/issues/314. - gasPrice.Add(gasPrice, gasPrice) - return gasPrice -} - -// Helper simplifying use via an option of a gas price appropriate for testing. -func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { - baseFee := SuggestGasPrice(ethClient) - return common.WithBaseFee(baseFee) -} +// // Sends an eth transaction, waits for the transaction receipt to be issued +// // and checks that the receipt indicates success. +// func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { +// require := require.New(ginkgo.GinkgoT()) + +// txID := signedTx.Hash() +// tests.Outf(" sending eth transaction with ID: %s\n", txID) + +// require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) + +// // Wait for the receipt +// var receipt *types.Receipt +// Eventually(func() bool { +// var err error +// receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) +// if errors.Is(err, interfaces.NotFound) { +// return false // Transaction is still pending +// } +// require.NoError(err) +// return true +// }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") + +// require.Equal(receipt.Status, types.ReceiptStatusSuccessful) +// return receipt +// } + +// // Determines the suggested gas price for the configured client that will +// // maximize the chances of transaction acceptance. +// func SuggestGasPrice(ethClient ethclient.Client) *big.Int { +// gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) +// require.NoError(ginkgo.GinkgoT(), err) +// // Double the suggested gas price to maximize the chances of +// // acceptance. Maybe this can be revisited pending resolution of +// // https://github.com/ava-labs/coreth/issues/314. +// gasPrice.Add(gasPrice, gasPrice) +// return gasPrice +// } + +// // Helper simplifying use via an option of a gas price appropriate for testing. +// func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { +// baseFee := SuggestGasPrice(ethClient) +// return common.WithBaseFee(baseFee) +// } // Verify that a new node can bootstrap into the network. func CheckBootstrapIsPossible(network testnet.Network) { diff --git a/tests/e2e/p/interchain_workflow.go b/tests/e2e/p/interchain_workflow.go index 10c15fd002a7..c5bc47517967 100644 --- a/tests/e2e/p/interchain_workflow.go +++ b/tests/e2e/p/interchain_workflow.go @@ -3,226 +3,226 @@ package p -import ( - "math/big" - "time" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/spf13/cast" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/api/info" - "github.com/ava-labs/avalanchego/config" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/tests/fixture/testnet" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/platformvm/reward" - "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { - require := require.New(ginkgo.GinkgoT()) - - const ( - transferAmount = 10 * units.Avax - weight = 2_000 * units.Avax // Used for both validation and delegation - ) - - ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { - network := e2e.Env.GetNetwork() - - ginkgo.By("checking that the network has a compatible minimum stake duration", func() { - minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) - require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) - }) - - ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") - factory := secp256k1.Factory{} - recipientKey, err := factory.NewPrivateKey() - require.NoError(err) - keychain := e2e.Env.NewKeychain(1) - keychain.Add(recipientKey) - nodeURI := e2e.Env.GetRandomNodeURI() - baseWallet := e2e.Env.NewWallet(keychain, nodeURI) - xWallet := baseWallet.X() - cWallet := baseWallet.C() - pWallet := baseWallet.P() - - ginkgo.By("defining common configuration") - recipientEthAddress := evm.GetEthAddress(recipientKey) - avaxAssetID := xWallet.AVAXAssetID() - // Use the same owner for sending to X-Chain and importing funds to P-Chain - recipientOwner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - recipientKey.Address(), - }, - } - // Use the same outputs for both X-Chain and C-Chain exports - exportOutputs := []*avax.TransferableOutput{ - { - Asset: avax.Asset{ - ID: avaxAssetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: transferAmount, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - keychain.Keys[0].Address(), - }, - }, - }, - }, - } - - ginkgo.By("adding new node and waiting for it to report healthy") - node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) - e2e.WaitForHealthy(node) - - ginkgo.By("retrieving new node's id and pop") - infoClient := info.NewClient(node.GetProcessContext().URI) - nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) - require.NoError(err) - - ginkgo.By("adding the new node as a validator", func() { - startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) - // Validation duration doesn't actually matter to this - // test - it is only ensuring that adding a validator - // doesn't break interchain transfer. - endTime := startTime.Add(30 * time.Second) - - rewardKey, err := factory.NewPrivateKey() - require.NoError(err) - - const ( - delegationPercent = 0.10 // 10% - delegationShare = reward.PercentDenominator * delegationPercent - ) - - _, err = pWallet.IssueAddPermissionlessValidatorTx( - &txs.SubnetValidator{ - Validator: txs.Validator{ - NodeID: nodeID, - Start: uint64(startTime.Unix()), - End: uint64(endTime.Unix()), - Wght: weight, - }, - Subnet: constants.PrimaryNetworkID, - }, - nodePOP, - pWallet.AVAXAssetID(), - &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{rewardKey.Address()}, - }, - &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{rewardKey.Address()}, - }, - delegationShare, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("adding a delegator to the new node", func() { - startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) - // Delegation duration doesn't actually matter to this - // test - it is only ensuring that adding a delegator - // doesn't break interchain transfer. - endTime := startTime.Add(15 * time.Second) - - rewardKey, err := factory.NewPrivateKey() - require.NoError(err) - - _, err = pWallet.IssueAddPermissionlessDelegatorTx( - &txs.SubnetValidator{ - Validator: txs.Validator{ - NodeID: nodeID, - Start: uint64(startTime.Unix()), - End: uint64(endTime.Unix()), - Wght: weight, - }, - Subnet: constants.PrimaryNetworkID, - }, - pWallet.AVAXAssetID(), - &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{rewardKey.Address()}, - }, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { - _, err := pWallet.IssueExportTx( - xWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { - _, err := xWallet.IssueImportTx( - constants.PlatformChainID, - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { - balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { - _, err := pWallet.IssueExportTx( - cWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("initializing a new eth client") - ethClient := e2e.Env.NewEthClient(nodeURI) - - ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { - _, err := cWallet.IssueImportTx( - constants.PlatformChainID, - recipientEthAddress, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") - balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) - require.NoError(err) - require.Positive(balance.Cmp(big.NewInt(0))) - - ginkgo.By("stopping validator node to free up resources for a bootstrap check") - require.NoError(node.Stop()) - - e2e.CheckBootstrapIsPossible(network) - }) -}) +// import ( +// "math/big" +// "time" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/spf13/cast" + +// "github.com/stretchr/testify/require" + +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/api/info" +// "github.com/ava-labs/avalanchego/config" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/tests/fixture/testnet" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/platformvm/reward" +// "github.com/ava-labs/avalanchego/vms/platformvm/txs" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { +// require := require.New(ginkgo.GinkgoT()) + +// const ( +// transferAmount = 10 * units.Avax +// weight = 2_000 * units.Avax // Used for both validation and delegation +// ) + +// ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { +// network := e2e.Env.GetNetwork() + +// ginkgo.By("checking that the network has a compatible minimum stake duration", func() { +// minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) +// require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) +// }) + +// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") +// factory := secp256k1.Factory{} +// recipientKey, err := factory.NewPrivateKey() +// require.NoError(err) +// keychain := e2e.Env.NewKeychain(1) +// keychain.Add(recipientKey) +// nodeURI := e2e.Env.GetRandomNodeURI() +// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) +// xWallet := baseWallet.X() +// cWallet := baseWallet.C() +// pWallet := baseWallet.P() + +// ginkgo.By("defining common configuration") +// recipientEthAddress := evm.GetEthAddress(recipientKey) +// avaxAssetID := xWallet.AVAXAssetID() +// // Use the same owner for sending to X-Chain and importing funds to P-Chain +// recipientOwner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// recipientKey.Address(), +// }, +// } +// // Use the same outputs for both X-Chain and C-Chain exports +// exportOutputs := []*avax.TransferableOutput{ +// { +// Asset: avax.Asset{ +// ID: avaxAssetID, +// }, +// Out: &secp256k1fx.TransferOutput{ +// Amt: transferAmount, +// OutputOwners: secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// keychain.Keys[0].Address(), +// }, +// }, +// }, +// }, +// } + +// ginkgo.By("adding new node and waiting for it to report healthy") +// node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) +// e2e.WaitForHealthy(node) + +// ginkgo.By("retrieving new node's id and pop") +// infoClient := info.NewClient(node.GetProcessContext().URI) +// nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) +// require.NoError(err) + +// ginkgo.By("adding the new node as a validator", func() { +// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) +// // Validation duration doesn't actually matter to this +// // test - it is only ensuring that adding a validator +// // doesn't break interchain transfer. +// endTime := startTime.Add(30 * time.Second) + +// rewardKey, err := factory.NewPrivateKey() +// require.NoError(err) + +// const ( +// delegationPercent = 0.10 // 10% +// delegationShare = reward.PercentDenominator * delegationPercent +// ) + +// _, err = pWallet.IssueAddPermissionlessValidatorTx( +// &txs.SubnetValidator{ +// Validator: txs.Validator{ +// NodeID: nodeID, +// Start: uint64(startTime.Unix()), +// End: uint64(endTime.Unix()), +// Wght: weight, +// }, +// Subnet: constants.PrimaryNetworkID, +// }, +// nodePOP, +// pWallet.AVAXAssetID(), +// &secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{rewardKey.Address()}, +// }, +// &secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{rewardKey.Address()}, +// }, +// delegationShare, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("adding a delegator to the new node", func() { +// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) +// // Delegation duration doesn't actually matter to this +// // test - it is only ensuring that adding a delegator +// // doesn't break interchain transfer. +// endTime := startTime.Add(15 * time.Second) + +// rewardKey, err := factory.NewPrivateKey() +// require.NoError(err) + +// _, err = pWallet.IssueAddPermissionlessDelegatorTx( +// &txs.SubnetValidator{ +// Validator: txs.Validator{ +// NodeID: nodeID, +// Start: uint64(startTime.Unix()), +// End: uint64(endTime.Unix()), +// Wght: weight, +// }, +// Subnet: constants.PrimaryNetworkID, +// }, +// pWallet.AVAXAssetID(), +// &secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{rewardKey.Address()}, +// }, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { +// _, err := pWallet.IssueExportTx( +// xWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { +// _, err := xWallet.IssueImportTx( +// constants.PlatformChainID, +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { +// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { +// _, err := pWallet.IssueExportTx( +// cWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("initializing a new eth client") +// ethClient := e2e.Env.NewEthClient(nodeURI) + +// ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { +// _, err := cWallet.IssueImportTx( +// constants.PlatformChainID, +// recipientEthAddress, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") +// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) +// require.NoError(err) +// require.Positive(balance.Cmp(big.NewInt(0))) + +// ginkgo.By("stopping validator node to free up resources for a bootstrap check") +// require.NoError(node.Stop()) + +// e2e.CheckBootstrapIsPossible(network) +// }) +// }) diff --git a/tests/e2e/x/interchain_workflow.go b/tests/e2e/x/interchain_workflow.go index 550689ff60c9..5443e1a54ad4 100644 --- a/tests/e2e/x/interchain_workflow.go +++ b/tests/e2e/x/interchain_workflow.go @@ -3,152 +3,152 @@ package x -import ( - "math/big" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { - require := require.New(ginkgo.GinkgoT()) - - const transferAmount = 10 * units.Avax - - ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { - nodeURI := e2e.Env.GetRandomNodeURI() - - ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") - factory := secp256k1.Factory{} - recipientKey, err := factory.NewPrivateKey() - require.NoError(err) - keychain := e2e.Env.NewKeychain(1) - keychain.Add(recipientKey) - baseWallet := e2e.Env.NewWallet(keychain, nodeURI) - xWallet := baseWallet.X() - cWallet := baseWallet.C() - pWallet := baseWallet.P() - - ginkgo.By("defining common configuration") - recipientEthAddress := evm.GetEthAddress(recipientKey) - avaxAssetID := xWallet.AVAXAssetID() - // Use the same owner for sending to X-Chain and importing funds to P-Chain - recipientOwner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - recipientKey.Address(), - }, - } - // Use the same outputs for both C-Chain and P-Chain exports - exportOutputs := []*avax.TransferableOutput{ - { - Asset: avax.Asset{ - ID: avaxAssetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: transferAmount, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - keychain.Keys[0].Address(), - }, - }, - }, - }, - } - - ginkgo.By("sending funds from one address to another on the X-Chain", func() { - _, err = xWallet.IssueBaseTx( - []*avax.TransferableOutput{{ - Asset: avax.Asset{ - ID: avaxAssetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: transferAmount, - OutputOwners: recipientOwner, - }, - }}, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { - balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { - _, err := xWallet.IssueExportTx( - cWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("initializing a new eth client") - ethClient := e2e.Env.NewEthClient(nodeURI) - - ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { - _, err := cWallet.IssueImportTx( - xWallet.BlockchainID(), - recipientEthAddress, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") - e2e.Eventually(func() bool { - balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) - require.NoError(err) - return balance.Cmp(big.NewInt(0)) > 0 - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") - - ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { - _, err := xWallet.IssueExportTx( - constants.PlatformChainID, - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { - _, err := pWallet.IssueImportTx( - xWallet.BlockchainID(), - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { - balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) - }) -}) +// import ( +// "math/big" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/stretchr/testify/require" + +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { +// require := require.New(ginkgo.GinkgoT()) + +// const transferAmount = 10 * units.Avax + +// ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { +// nodeURI := e2e.Env.GetRandomNodeURI() + +// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") +// factory := secp256k1.Factory{} +// recipientKey, err := factory.NewPrivateKey() +// require.NoError(err) +// keychain := e2e.Env.NewKeychain(1) +// keychain.Add(recipientKey) +// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) +// xWallet := baseWallet.X() +// cWallet := baseWallet.C() +// pWallet := baseWallet.P() + +// ginkgo.By("defining common configuration") +// recipientEthAddress := evm.GetEthAddress(recipientKey) +// avaxAssetID := xWallet.AVAXAssetID() +// // Use the same owner for sending to X-Chain and importing funds to P-Chain +// recipientOwner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// recipientKey.Address(), +// }, +// } +// // Use the same outputs for both C-Chain and P-Chain exports +// exportOutputs := []*avax.TransferableOutput{ +// { +// Asset: avax.Asset{ +// ID: avaxAssetID, +// }, +// Out: &secp256k1fx.TransferOutput{ +// Amt: transferAmount, +// OutputOwners: secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// keychain.Keys[0].Address(), +// }, +// }, +// }, +// }, +// } + +// ginkgo.By("sending funds from one address to another on the X-Chain", func() { +// _, err = xWallet.IssueBaseTx( +// []*avax.TransferableOutput{{ +// Asset: avax.Asset{ +// ID: avaxAssetID, +// }, +// Out: &secp256k1fx.TransferOutput{ +// Amt: transferAmount, +// OutputOwners: recipientOwner, +// }, +// }}, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { +// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { +// _, err := xWallet.IssueExportTx( +// cWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("initializing a new eth client") +// ethClient := e2e.Env.NewEthClient(nodeURI) + +// ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { +// _, err := cWallet.IssueImportTx( +// xWallet.BlockchainID(), +// recipientEthAddress, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") +// e2e.Eventually(func() bool { +// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) +// require.NoError(err) +// return balance.Cmp(big.NewInt(0)) > 0 +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") + +// ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { +// _, err := xWallet.IssueExportTx( +// constants.PlatformChainID, +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { +// _, err := pWallet.IssueImportTx( +// xWallet.BlockchainID(), +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { +// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) +// }) +// }) diff --git a/tests/fixture/testnet/config.go b/tests/fixture/testnet/config.go index 10d51104eef4..73537ea74744 100644 --- a/tests/fixture/testnet/config.go +++ b/tests/fixture/testnet/config.go @@ -15,9 +15,9 @@ import ( "github.com/spf13/cast" - "github.com/ava-labs/coreth/core" - "github.com/ava-labs/coreth/params" - "github.com/ava-labs/coreth/plugin/evm" + // "github.com/ava-labs/coreth/core" + // "github.com/ava-labs/coreth/params" + // "github.com/ava-labs/coreth/plugin/evm" "github.com/ava-labs/avalanchego/config" "github.com/ava-labs/avalanchego/genesis" @@ -143,15 +143,15 @@ func (c *NetworkConfig) EnsureGenesis(networkID uint32, validatorIDs []ids.NodeI // Ensure pre-funded keys have arbitrary large balances on both chains to support testing xChainBalances := make(XChainBalanceMap, len(c.FundedKeys)) - cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) - for _, key := range c.FundedKeys { - xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount - cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ - Balance: DefaultFundedKeyCChainAmount, - } - } - - genesis, err := NewTestGenesis(networkID, xChainBalances, cChainBalances, validatorIDs) + // cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) + // for _, key := range c.FundedKeys { + // xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount + // cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ + // Balance: DefaultFundedKeyCChainAmount, + // } + // } + + genesis, err := NewTestGenesis(networkID, xChainBalances /*, cChainBalances,*/, validatorIDs) if err != nil { return err } @@ -311,7 +311,7 @@ type XChainBalanceMap map[ids.ShortID]uint64 func NewTestGenesis( networkID uint32, xChainBalances XChainBalanceMap, - cChainBalances core.GenesisAlloc, + // cChainBalances core.GenesisAlloc, validatorIDs []ids.NodeID, ) (*genesis.UnparsedConfig, error) { // Validate inputs @@ -322,7 +322,7 @@ func NewTestGenesis( if len(validatorIDs) == 0 { return nil, errMissingValidatorsForGenesis } - if len(xChainBalances) == 0 || len(cChainBalances) == 0 { + if len(xChainBalances) == 0 /*|| len(cChainBalances) == 0*/ { return nil, errMissingBalancesForGenesis } @@ -394,20 +394,20 @@ func NewTestGenesis( ) } - // Define C-Chain genesis - cChainGenesis := &core.Genesis{ - Config: ¶ms.ChainConfig{ - ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary - }, - Difficulty: big.NewInt(0), // Difficulty is a mandatory field - GasLimit: DefaultGasLimit, - Alloc: cChainBalances, - } - cChainGenesisBytes, err := json.Marshal(cChainGenesis) - if err != nil { - return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) - } - config.CChainGenesis = string(cChainGenesisBytes) + // // Define C-Chain genesis + // cChainGenesis := &core.Genesis{ + // Config: ¶ms.ChainConfig{ + // ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary + // }, + // Difficulty: big.NewInt(0), // Difficulty is a mandatory field + // GasLimit: DefaultGasLimit, + // Alloc: cChainBalances, + // } + // cChainGenesisBytes, err := json.Marshal(cChainGenesis) + // if err != nil { + // return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) + // } + // config.CChainGenesis = string(cChainGenesisBytes) // Give staking rewards for initial validators to a random address. Any testing of staking rewards // will be easier to perform with nodes other than the initial validators since the timing of diff --git a/vms/example/xsvm/cmd/chain/create/cmd.go b/vms/example/xsvm/cmd/chain/create/cmd.go index 1f00491a4ce6..043b4298dcdf 100644 --- a/vms/example/xsvm/cmd/chain/create/cmd.go +++ b/vms/example/xsvm/cmd/chain/create/cmd.go @@ -42,9 +42,9 @@ func createFunc(c *cobra.Command, args []string) error { // that [uri] is hosting. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: config.URI, - AVAXKeychain: kc, - EthKeychain: kc, + URI: config.URI, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(config.SubnetID), }) if err != nil { diff --git a/wallet/chain/c/backend.go b/wallet/chain/c/backend.go index 0a735116b646..b88c8c643bc3 100644 --- a/wallet/chain/c/backend.go +++ b/wallet/chain/c/backend.go @@ -3,153 +3,153 @@ package c -import ( - "errors" - "fmt" - "math/big" - "sync" - - stdcontext "context" - - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/utils/math" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var ( - _ Backend = (*backend)(nil) - - errUnknownTxType = errors.New("unknown tx type") -) - -// Backend defines the full interface required to support a C-chain wallet. -type Backend interface { - common.ChainUTXOs - BuilderBackend - SignerBackend - - AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error -} - -type backend struct { - Context - common.ChainUTXOs - - accountsLock sync.RWMutex - accounts map[ethcommon.Address]*Account -} - -type Account struct { - Balance *big.Int - Nonce uint64 -} - -func NewBackend( - ctx Context, - utxos common.ChainUTXOs, - accounts map[ethcommon.Address]*Account, -) Backend { - return &backend{ - Context: ctx, - ChainUTXOs: utxos, - accounts: accounts, - } -} - -func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { - switch tx := tx.UnsignedAtomicTx.(type) { - case *evm.UnsignedImportTx: - for _, input := range tx.ImportedInputs { - utxoID := input.InputID() - if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { - return err - } - } - - b.accountsLock.Lock() - defer b.accountsLock.Unlock() - - for _, output := range tx.Outs { - account, ok := b.accounts[output.Address] - if !ok { - continue - } - - balance := new(big.Int).SetUint64(output.Amount) - balance.Mul(balance, avaxConversionRate) - account.Balance.Add(account.Balance, balance) - } - case *evm.UnsignedExportTx: - txID := tx.ID() - for i, out := range tx.ExportedOutputs { - err := b.AddUTXO( - ctx, - tx.DestinationChain, - &avax.UTXO{ - UTXOID: avax.UTXOID{ - TxID: txID, - OutputIndex: uint32(i), - }, - Asset: avax.Asset{ID: out.AssetID()}, - Out: out.Out, - }, - ) - if err != nil { - return err - } - } - - b.accountsLock.Lock() - defer b.accountsLock.Unlock() - - for _, input := range tx.Ins { - account, ok := b.accounts[input.Address] - if !ok { - continue - } - - balance := new(big.Int).SetUint64(input.Amount) - balance.Mul(balance, avaxConversionRate) - if account.Balance.Cmp(balance) == -1 { - return errInsufficientFunds - } - account.Balance.Sub(account.Balance, balance) - - newNonce, err := math.Add64(input.Nonce, 1) - if err != nil { - return err - } - account.Nonce = newNonce - } - default: - return fmt.Errorf("%w: %T", errUnknownTxType, tx) - } - return nil -} - -func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { - b.accountsLock.RLock() - defer b.accountsLock.RUnlock() - - account, exists := b.accounts[addr] - if !exists { - return nil, database.ErrNotFound - } - return account.Balance, nil -} - -func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { - b.accountsLock.RLock() - defer b.accountsLock.RUnlock() - - account, exists := b.accounts[addr] - if !exists { - return 0, database.ErrNotFound - } - return account.Nonce, nil -} +// import ( +// "errors" +// "fmt" +// "math/big" +// "sync" + +// stdcontext "context" + +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/database" +// "github.com/ava-labs/avalanchego/utils/math" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var ( +// _ Backend = (*backend)(nil) + +// errUnknownTxType = errors.New("unknown tx type") +// ) + +// // Backend defines the full interface required to support a C-chain wallet. +// type Backend interface { +// common.ChainUTXOs +// BuilderBackend +// SignerBackend + +// AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error +// } + +// type backend struct { +// Context +// common.ChainUTXOs + +// accountsLock sync.RWMutex +// accounts map[ethcommon.Address]*Account +// } + +// type Account struct { +// Balance *big.Int +// Nonce uint64 +// } + +// func NewBackend( +// ctx Context, +// utxos common.ChainUTXOs, +// accounts map[ethcommon.Address]*Account, +// ) Backend { +// return &backend{ +// Context: ctx, +// ChainUTXOs: utxos, +// accounts: accounts, +// } +// } + +// func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { +// switch tx := tx.UnsignedAtomicTx.(type) { +// case *evm.UnsignedImportTx: +// for _, input := range tx.ImportedInputs { +// utxoID := input.InputID() +// if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { +// return err +// } +// } + +// b.accountsLock.Lock() +// defer b.accountsLock.Unlock() + +// for _, output := range tx.Outs { +// account, ok := b.accounts[output.Address] +// if !ok { +// continue +// } + +// balance := new(big.Int).SetUint64(output.Amount) +// balance.Mul(balance, avaxConversionRate) +// account.Balance.Add(account.Balance, balance) +// } +// case *evm.UnsignedExportTx: +// txID := tx.ID() +// for i, out := range tx.ExportedOutputs { +// err := b.AddUTXO( +// ctx, +// tx.DestinationChain, +// &avax.UTXO{ +// UTXOID: avax.UTXOID{ +// TxID: txID, +// OutputIndex: uint32(i), +// }, +// Asset: avax.Asset{ID: out.AssetID()}, +// Out: out.Out, +// }, +// ) +// if err != nil { +// return err +// } +// } + +// b.accountsLock.Lock() +// defer b.accountsLock.Unlock() + +// for _, input := range tx.Ins { +// account, ok := b.accounts[input.Address] +// if !ok { +// continue +// } + +// balance := new(big.Int).SetUint64(input.Amount) +// balance.Mul(balance, avaxConversionRate) +// if account.Balance.Cmp(balance) == -1 { +// return errInsufficientFunds +// } +// account.Balance.Sub(account.Balance, balance) + +// newNonce, err := math.Add64(input.Nonce, 1) +// if err != nil { +// return err +// } +// account.Nonce = newNonce +// } +// default: +// return fmt.Errorf("%w: %T", errUnknownTxType, tx) +// } +// return nil +// } + +// func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { +// b.accountsLock.RLock() +// defer b.accountsLock.RUnlock() + +// account, exists := b.accounts[addr] +// if !exists { +// return nil, database.ErrNotFound +// } +// return account.Balance, nil +// } + +// func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { +// b.accountsLock.RLock() +// defer b.accountsLock.RUnlock() + +// account, exists := b.accounts[addr] +// if !exists { +// return 0, database.ErrNotFound +// } +// return account.Nonce, nil +// } diff --git a/wallet/chain/c/builder.go b/wallet/chain/c/builder.go index d2d088e88a53..c51d2647777e 100644 --- a/wallet/chain/c/builder.go +++ b/wallet/chain/c/builder.go @@ -3,399 +3,399 @@ package c -import ( - "errors" - "math/big" - - stdcontext "context" - - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils" - "github.com/ava-labs/avalanchego/utils/math" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -const avaxConversionRateInt = 1_000_000_000 - -var ( - _ Builder = (*builder)(nil) - - errInsufficientFunds = errors.New("insufficient funds") - - // avaxConversionRate is the conversion rate between the smallest - // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest - // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. - // - // This is only required for AVAX because the denomination of 1 AVAX is 9 - // decimal places on the X and P chains, but is 18 decimal places within the - // EVM. - avaxConversionRate = big.NewInt(avaxConversionRateInt) -) - -// Builder provides a convenient interface for building unsigned C-chain -// transactions. -type Builder interface { - // GetBalance calculates the amount of AVAX that this builder has control - // over. - GetBalance( - options ...common.Option, - ) (*big.Int, error) - - // GetImportableBalance calculates the amount of AVAX that this builder - // could import from the provided chain. - // - // - [chainID] specifies the chain the funds are from. - GetImportableBalance( - chainID ids.ID, - options ...common.Option, - ) (uint64, error) - - // NewImportTx creates an import transaction that attempts to consume all - // the available UTXOs and import the funds to [to]. - // - // - [chainID] specifies the chain to be importing funds from. - // - [to] specifies where to send the imported funds to. - // - [baseFee] specifies the fee price willing to be paid by this tx. - NewImportTx( - chainID ids.ID, - to ethcommon.Address, - baseFee *big.Int, - options ...common.Option, - ) (*evm.UnsignedImportTx, error) - - // NewExportTx creates an export transaction that attempts to send all the - // provided [outputs] to the requested [chainID]. - // - // - [chainID] specifies the chain to be exporting the funds to. - // - [outputs] specifies the outputs to send to the [chainID]. - // - [baseFee] specifies the fee price willing to be paid by this tx. - NewExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - baseFee *big.Int, - options ...common.Option, - ) (*evm.UnsignedExportTx, error) -} - -// BuilderBackend specifies the required information needed to build unsigned -// C-chain transactions. -type BuilderBackend interface { - Context - - UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) - Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) - Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) -} - -type builder struct { - avaxAddrs set.Set[ids.ShortID] - ethAddrs set.Set[ethcommon.Address] - backend BuilderBackend -} - -// NewBuilder returns a new transaction builder. -// -// - [avaxAddrs] is the set of addresses in the AVAX format that the builder -// assumes can be used when signing the transactions in the future. -// - [ethAddrs] is the set of addresses in the Eth format that the builder -// assumes can be used when signing the transactions in the future. -// - [backend] provides the required access to the chain's context and state -// to build out the transactions. -func NewBuilder( - avaxAddrs set.Set[ids.ShortID], - ethAddrs set.Set[ethcommon.Address], - backend BuilderBackend, -) Builder { - return &builder{ - avaxAddrs: avaxAddrs, - ethAddrs: ethAddrs, - backend: backend, - } -} - -func (b *builder) GetBalance( - options ...common.Option, -) (*big.Int, error) { - var ( - ops = common.NewOptions(options) - ctx = ops.Context() - addrs = ops.EthAddresses(b.ethAddrs) - totalBalance = new(big.Int) - ) - for addr := range addrs { - balance, err := b.backend.Balance(ctx, addr) - if err != nil { - return nil, err - } - totalBalance.Add(totalBalance, balance) - } - - return totalBalance, nil -} - -func (b *builder) GetImportableBalance( - chainID ids.ID, - options ...common.Option, -) (uint64, error) { - ops := common.NewOptions(options) - utxos, err := b.backend.UTXOs(ops.Context(), chainID) - if err != nil { - return 0, err - } - - var ( - addrs = ops.Addresses(b.avaxAddrs) - minIssuanceTime = ops.MinIssuanceTime() - avaxAssetID = b.backend.AVAXAssetID() - balance uint64 - ) - for _, utxo := range utxos { - amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) - if !ok { - continue - } - - newBalance, err := math.Add64(balance, amount) - if err != nil { - return 0, err - } - balance = newBalance - } - - return balance, nil -} - -func (b *builder) NewImportTx( - chainID ids.ID, - to ethcommon.Address, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedImportTx, error) { - ops := common.NewOptions(options) - utxos, err := b.backend.UTXOs(ops.Context(), chainID) - if err != nil { - return nil, err - } - - var ( - addrs = ops.Addresses(b.avaxAddrs) - minIssuanceTime = ops.MinIssuanceTime() - avaxAssetID = b.backend.AVAXAssetID() - - importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) - importedAmount uint64 - ) - for _, utxo := range utxos { - amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) - if !ok { - continue - } - - importedInputs = append(importedInputs, &avax.TransferableInput{ - UTXOID: utxo.UTXOID, - Asset: utxo.Asset, - In: &secp256k1fx.TransferInput{ - Amt: amount, - Input: secp256k1fx.Input{ - SigIndices: inputSigIndices, - }, - }, - }) - - newImportedAmount, err := math.Add64(importedAmount, amount) - if err != nil { - return nil, err - } - importedAmount = newImportedAmount - } - - utils.Sort(importedInputs) - tx := &evm.UnsignedImportTx{ - NetworkID: b.backend.NetworkID(), - BlockchainID: b.backend.BlockchainID(), - SourceChain: chainID, - ImportedInputs: importedInputs, - } - - // We must initialize the bytes of the tx to calculate the initial cost - wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} - if err := wrappedTx.Sign(evm.Codec, nil); err != nil { - return nil, err - } - - gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) - if err != nil { - return nil, err - } - gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas - - txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) - if err != nil { - return nil, err - } - - if importedAmount <= txFee { - return nil, errInsufficientFunds - } - - tx.Outs = []evm.EVMOutput{{ - Address: to, - Amount: importedAmount - txFee, - AssetID: avaxAssetID, - }} - return tx, nil -} - -func (b *builder) NewExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedExportTx, error) { - var ( - avaxAssetID = b.backend.AVAXAssetID() - exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) - exportedAmount uint64 - ) - for i, output := range outputs { - exportedOutputs[i] = &avax.TransferableOutput{ - Asset: avax.Asset{ID: avaxAssetID}, - Out: output, - } - - newExportedAmount, err := math.Add64(exportedAmount, output.Amt) - if err != nil { - return nil, err - } - exportedAmount = newExportedAmount - } - - avax.SortTransferableOutputs(exportedOutputs, evm.Codec) - tx := &evm.UnsignedExportTx{ - NetworkID: b.backend.NetworkID(), - BlockchainID: b.backend.BlockchainID(), - DestinationChain: chainID, - ExportedOutputs: exportedOutputs, - } - - // We must initialize the bytes of the tx to calculate the initial cost - wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} - if err := wrappedTx.Sign(evm.Codec, nil); err != nil { - return nil, err - } - - cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) - if err != nil { - return nil, err - } - - initialFee, err := evm.CalculateDynamicFee(cost, baseFee) - if err != nil { - return nil, err - } - - amountToConsume, err := math.Add64(exportedAmount, initialFee) - if err != nil { - return nil, err - } - - var ( - ops = common.NewOptions(options) - ctx = ops.Context() - addrs = ops.EthAddresses(b.ethAddrs) - inputs = make([]evm.EVMInput, 0, addrs.Len()) - ) - for addr := range addrs { - if amountToConsume == 0 { - break - } - - prevFee, err := evm.CalculateDynamicFee(cost, baseFee) - if err != nil { - return nil, err - } - - newCost := cost + evm.EVMInputGas - newFee, err := evm.CalculateDynamicFee(newCost, baseFee) - if err != nil { - return nil, err - } - - additionalFee := newFee - prevFee - - balance, err := b.backend.Balance(ctx, addr) - if err != nil { - return nil, err - } - - // Since the asset is AVAX, we divide by the avaxConversionRate to - // convert back to the correct denomination of AVAX that can be - // exported. - avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() - - // If the balance for [addr] is insufficient to cover the additional - // cost of adding an input to the transaction, skip adding the input - // altogether. - if avaxBalance <= additionalFee { - continue - } - - // Update the cost for the next iteration - cost = newCost - - amountToConsume, err = math.Add64(amountToConsume, additionalFee) - if err != nil { - return nil, err - } - - nonce, err := b.backend.Nonce(ctx, addr) - if err != nil { - return nil, err - } - - inputAmount := math.Min(amountToConsume, avaxBalance) - inputs = append(inputs, evm.EVMInput{ - Address: addr, - Amount: inputAmount, - AssetID: avaxAssetID, - Nonce: nonce, - }) - amountToConsume -= inputAmount - } - - if amountToConsume > 0 { - return nil, errInsufficientFunds - } - - utils.Sort(inputs) - tx.Ins = inputs - return tx, nil -} - -func getSpendableAmount( - utxo *avax.UTXO, - addrs set.Set[ids.ShortID], - minIssuanceTime uint64, - avaxAssetID ids.ID, -) (uint64, []uint32, bool) { - if utxo.Asset.ID != avaxAssetID { - // Only AVAX can be imported - return 0, nil, false - } - - out, ok := utxo.Out.(*secp256k1fx.TransferOutput) - if !ok { - // Can't import an unknown transfer output type - return 0, nil, false - } - - inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) - return out.Amt, inputSigIndices, ok -} +// import ( +// "errors" +// "math/big" + +// stdcontext "context" + +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils" +// "github.com/ava-labs/avalanchego/utils/math" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// const avaxConversionRateInt = 1_000_000_000 + +// var ( +// _ Builder = (*builder)(nil) + +// errInsufficientFunds = errors.New("insufficient funds") + +// // avaxConversionRate is the conversion rate between the smallest +// // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest +// // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. +// // +// // This is only required for AVAX because the denomination of 1 AVAX is 9 +// // decimal places on the X and P chains, but is 18 decimal places within the +// // EVM. +// avaxConversionRate = big.NewInt(avaxConversionRateInt) +// ) + +// // Builder provides a convenient interface for building unsigned C-chain +// // transactions. +// type Builder interface { +// // GetBalance calculates the amount of AVAX that this builder has control +// // over. +// GetBalance( +// options ...common.Option, +// ) (*big.Int, error) + +// // GetImportableBalance calculates the amount of AVAX that this builder +// // could import from the provided chain. +// // +// // - [chainID] specifies the chain the funds are from. +// GetImportableBalance( +// chainID ids.ID, +// options ...common.Option, +// ) (uint64, error) + +// // NewImportTx creates an import transaction that attempts to consume all +// // the available UTXOs and import the funds to [to]. +// // +// // - [chainID] specifies the chain to be importing funds from. +// // - [to] specifies where to send the imported funds to. +// // - [baseFee] specifies the fee price willing to be paid by this tx. +// NewImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedImportTx, error) + +// // NewExportTx creates an export transaction that attempts to send all the +// // provided [outputs] to the requested [chainID]. +// // +// // - [chainID] specifies the chain to be exporting the funds to. +// // - [outputs] specifies the outputs to send to the [chainID]. +// // - [baseFee] specifies the fee price willing to be paid by this tx. +// NewExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedExportTx, error) +// } + +// // BuilderBackend specifies the required information needed to build unsigned +// // C-chain transactions. +// type BuilderBackend interface { +// Context + +// UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) +// Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) +// Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) +// } + +// type builder struct { +// avaxAddrs set.Set[ids.ShortID] +// ethAddrs set.Set[ethcommon.Address] +// backend BuilderBackend +// } + +// // NewBuilder returns a new transaction builder. +// // +// // - [avaxAddrs] is the set of addresses in the AVAX format that the builder +// // assumes can be used when signing the transactions in the future. +// // - [ethAddrs] is the set of addresses in the Eth format that the builder +// // assumes can be used when signing the transactions in the future. +// // - [backend] provides the required access to the chain's context and state +// // to build out the transactions. +// func NewBuilder( +// avaxAddrs set.Set[ids.ShortID], +// ethAddrs set.Set[ethcommon.Address], +// backend BuilderBackend, +// ) Builder { +// return &builder{ +// avaxAddrs: avaxAddrs, +// ethAddrs: ethAddrs, +// backend: backend, +// } +// } + +// func (b *builder) GetBalance( +// options ...common.Option, +// ) (*big.Int, error) { +// var ( +// ops = common.NewOptions(options) +// ctx = ops.Context() +// addrs = ops.EthAddresses(b.ethAddrs) +// totalBalance = new(big.Int) +// ) +// for addr := range addrs { +// balance, err := b.backend.Balance(ctx, addr) +// if err != nil { +// return nil, err +// } +// totalBalance.Add(totalBalance, balance) +// } + +// return totalBalance, nil +// } + +// func (b *builder) GetImportableBalance( +// chainID ids.ID, +// options ...common.Option, +// ) (uint64, error) { +// ops := common.NewOptions(options) +// utxos, err := b.backend.UTXOs(ops.Context(), chainID) +// if err != nil { +// return 0, err +// } + +// var ( +// addrs = ops.Addresses(b.avaxAddrs) +// minIssuanceTime = ops.MinIssuanceTime() +// avaxAssetID = b.backend.AVAXAssetID() +// balance uint64 +// ) +// for _, utxo := range utxos { +// amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) +// if !ok { +// continue +// } + +// newBalance, err := math.Add64(balance, amount) +// if err != nil { +// return 0, err +// } +// balance = newBalance +// } + +// return balance, nil +// } + +// func (b *builder) NewImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedImportTx, error) { +// ops := common.NewOptions(options) +// utxos, err := b.backend.UTXOs(ops.Context(), chainID) +// if err != nil { +// return nil, err +// } + +// var ( +// addrs = ops.Addresses(b.avaxAddrs) +// minIssuanceTime = ops.MinIssuanceTime() +// avaxAssetID = b.backend.AVAXAssetID() + +// importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) +// importedAmount uint64 +// ) +// for _, utxo := range utxos { +// amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) +// if !ok { +// continue +// } + +// importedInputs = append(importedInputs, &avax.TransferableInput{ +// UTXOID: utxo.UTXOID, +// Asset: utxo.Asset, +// In: &secp256k1fx.TransferInput{ +// Amt: amount, +// Input: secp256k1fx.Input{ +// SigIndices: inputSigIndices, +// }, +// }, +// }) + +// newImportedAmount, err := math.Add64(importedAmount, amount) +// if err != nil { +// return nil, err +// } +// importedAmount = newImportedAmount +// } + +// utils.Sort(importedInputs) +// tx := &evm.UnsignedImportTx{ +// NetworkID: b.backend.NetworkID(), +// BlockchainID: b.backend.BlockchainID(), +// SourceChain: chainID, +// ImportedInputs: importedInputs, +// } + +// // We must initialize the bytes of the tx to calculate the initial cost +// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} +// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { +// return nil, err +// } + +// gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) +// if err != nil { +// return nil, err +// } +// gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas + +// txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) +// if err != nil { +// return nil, err +// } + +// if importedAmount <= txFee { +// return nil, errInsufficientFunds +// } + +// tx.Outs = []evm.EVMOutput{{ +// Address: to, +// Amount: importedAmount - txFee, +// AssetID: avaxAssetID, +// }} +// return tx, nil +// } + +// func (b *builder) NewExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedExportTx, error) { +// var ( +// avaxAssetID = b.backend.AVAXAssetID() +// exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) +// exportedAmount uint64 +// ) +// for i, output := range outputs { +// exportedOutputs[i] = &avax.TransferableOutput{ +// Asset: avax.Asset{ID: avaxAssetID}, +// Out: output, +// } + +// newExportedAmount, err := math.Add64(exportedAmount, output.Amt) +// if err != nil { +// return nil, err +// } +// exportedAmount = newExportedAmount +// } + +// avax.SortTransferableOutputs(exportedOutputs, evm.Codec) +// tx := &evm.UnsignedExportTx{ +// NetworkID: b.backend.NetworkID(), +// BlockchainID: b.backend.BlockchainID(), +// DestinationChain: chainID, +// ExportedOutputs: exportedOutputs, +// } + +// // We must initialize the bytes of the tx to calculate the initial cost +// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} +// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { +// return nil, err +// } + +// cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) +// if err != nil { +// return nil, err +// } + +// initialFee, err := evm.CalculateDynamicFee(cost, baseFee) +// if err != nil { +// return nil, err +// } + +// amountToConsume, err := math.Add64(exportedAmount, initialFee) +// if err != nil { +// return nil, err +// } + +// var ( +// ops = common.NewOptions(options) +// ctx = ops.Context() +// addrs = ops.EthAddresses(b.ethAddrs) +// inputs = make([]evm.EVMInput, 0, addrs.Len()) +// ) +// for addr := range addrs { +// if amountToConsume == 0 { +// break +// } + +// prevFee, err := evm.CalculateDynamicFee(cost, baseFee) +// if err != nil { +// return nil, err +// } + +// newCost := cost + evm.EVMInputGas +// newFee, err := evm.CalculateDynamicFee(newCost, baseFee) +// if err != nil { +// return nil, err +// } + +// additionalFee := newFee - prevFee + +// balance, err := b.backend.Balance(ctx, addr) +// if err != nil { +// return nil, err +// } + +// // Since the asset is AVAX, we divide by the avaxConversionRate to +// // convert back to the correct denomination of AVAX that can be +// // exported. +// avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() + +// // If the balance for [addr] is insufficient to cover the additional +// // cost of adding an input to the transaction, skip adding the input +// // altogether. +// if avaxBalance <= additionalFee { +// continue +// } + +// // Update the cost for the next iteration +// cost = newCost + +// amountToConsume, err = math.Add64(amountToConsume, additionalFee) +// if err != nil { +// return nil, err +// } + +// nonce, err := b.backend.Nonce(ctx, addr) +// if err != nil { +// return nil, err +// } + +// inputAmount := math.Min(amountToConsume, avaxBalance) +// inputs = append(inputs, evm.EVMInput{ +// Address: addr, +// Amount: inputAmount, +// AssetID: avaxAssetID, +// Nonce: nonce, +// }) +// amountToConsume -= inputAmount +// } + +// if amountToConsume > 0 { +// return nil, errInsufficientFunds +// } + +// utils.Sort(inputs) +// tx.Ins = inputs +// return tx, nil +// } + +// func getSpendableAmount( +// utxo *avax.UTXO, +// addrs set.Set[ids.ShortID], +// minIssuanceTime uint64, +// avaxAssetID ids.ID, +// ) (uint64, []uint32, bool) { +// if utxo.Asset.ID != avaxAssetID { +// // Only AVAX can be imported +// return 0, nil, false +// } + +// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) +// if !ok { +// // Can't import an unknown transfer output type +// return 0, nil, false +// } + +// inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) +// return out.Amt, inputSigIndices, ok +// } diff --git a/wallet/chain/c/builder_with_options.go b/wallet/chain/c/builder_with_options.go index 8416dddf9928..9b7ab8399484 100644 --- a/wallet/chain/c/builder_with_options.go +++ b/wallet/chain/c/builder_with_options.go @@ -3,81 +3,81 @@ package c -import ( - "math/big" +// import ( +// "math/big" - "github.com/ava-labs/coreth/plugin/evm" +// "github.com/ava-labs/coreth/plugin/evm" - ethcommon "github.com/ethereum/go-ethereum/common" +// ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) -var _ Builder = (*builderWithOptions)(nil) +// var _ Builder = (*builderWithOptions)(nil) -type builderWithOptions struct { - Builder - options []common.Option -} +// type builderWithOptions struct { +// Builder +// options []common.Option +// } -// NewBuilderWithOptions returns a new transaction builder that will use the -// given options by default. -// -// - [builder] is the builder that will be called to perform the underlying -// operations. -// - [options] will be provided to the builder in addition to the options -// provided in the method calls. -func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { - return &builderWithOptions{ - Builder: builder, - options: options, - } -} +// // NewBuilderWithOptions returns a new transaction builder that will use the +// // given options by default. +// // +// // - [builder] is the builder that will be called to perform the underlying +// // operations. +// // - [options] will be provided to the builder in addition to the options +// // provided in the method calls. +// func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { +// return &builderWithOptions{ +// Builder: builder, +// options: options, +// } +// } -func (b *builderWithOptions) GetBalance( - options ...common.Option, -) (*big.Int, error) { - return b.Builder.GetBalance( - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) GetBalance( +// options ...common.Option, +// ) (*big.Int, error) { +// return b.Builder.GetBalance( +// common.UnionOptions(b.options, options)..., +// ) +// } -func (b *builderWithOptions) GetImportableBalance( - chainID ids.ID, - options ...common.Option, -) (uint64, error) { - return b.Builder.GetImportableBalance( - chainID, - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) GetImportableBalance( +// chainID ids.ID, +// options ...common.Option, +// ) (uint64, error) { +// return b.Builder.GetImportableBalance( +// chainID, +// common.UnionOptions(b.options, options)..., +// ) +// } -func (b *builderWithOptions) NewImportTx( - chainID ids.ID, - to ethcommon.Address, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedImportTx, error) { - return b.Builder.NewImportTx( - chainID, - to, - baseFee, - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) NewImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedImportTx, error) { +// return b.Builder.NewImportTx( +// chainID, +// to, +// baseFee, +// common.UnionOptions(b.options, options)..., +// ) +// } -func (b *builderWithOptions) NewExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedExportTx, error) { - return b.Builder.NewExportTx( - chainID, - outputs, - baseFee, - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) NewExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedExportTx, error) { +// return b.Builder.NewExportTx( +// chainID, +// outputs, +// baseFee, +// common.UnionOptions(b.options, options)..., +// ) +// } diff --git a/wallet/chain/c/context.go b/wallet/chain/c/context.go index d506b42f81fa..1c01d8fb55c8 100644 --- a/wallet/chain/c/context.go +++ b/wallet/chain/c/context.go @@ -3,81 +3,81 @@ package c -import ( - stdcontext "context" +// import ( +// stdcontext "context" - "github.com/ava-labs/avalanchego/api/info" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/avm" -) +// "github.com/ava-labs/avalanchego/api/info" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/avm" +// ) -var _ Context = (*context)(nil) +// var _ Context = (*context)(nil) -type Context interface { - NetworkID() uint32 - BlockchainID() ids.ID - AVAXAssetID() ids.ID -} +// type Context interface { +// NetworkID() uint32 +// BlockchainID() ids.ID +// AVAXAssetID() ids.ID +// } -type context struct { - networkID uint32 - blockchainID ids.ID - avaxAssetID ids.ID -} +// type context struct { +// networkID uint32 +// blockchainID ids.ID +// avaxAssetID ids.ID +// } -func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { - infoClient := info.NewClient(uri) - xChainClient := avm.NewClient(uri, "X") - return NewContextFromClients(ctx, infoClient, xChainClient) -} +// func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { +// infoClient := info.NewClient(uri) +// xChainClient := avm.NewClient(uri, "X") +// return NewContextFromClients(ctx, infoClient, xChainClient) +// } -func NewContextFromClients( - ctx stdcontext.Context, - infoClient info.Client, - xChainClient avm.Client, -) (Context, error) { - networkID, err := infoClient.GetNetworkID(ctx) - if err != nil { - return nil, err - } +// func NewContextFromClients( +// ctx stdcontext.Context, +// infoClient info.Client, +// xChainClient avm.Client, +// ) (Context, error) { +// networkID, err := infoClient.GetNetworkID(ctx) +// if err != nil { +// return nil, err +// } - chainID, err := infoClient.GetBlockchainID(ctx, "C") - if err != nil { - return nil, err - } +// chainID, err := infoClient.GetBlockchainID(ctx, "C") +// if err != nil { +// return nil, err +// } - asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") - if err != nil { - return nil, err - } +// asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") +// if err != nil { +// return nil, err +// } - return NewContext( - networkID, - chainID, - asset.AssetID, - ), nil -} +// return NewContext( +// networkID, +// chainID, +// asset.AssetID, +// ), nil +// } -func NewContext( - networkID uint32, - blockchainID ids.ID, - avaxAssetID ids.ID, -) Context { - return &context{ - networkID: networkID, - blockchainID: blockchainID, - avaxAssetID: avaxAssetID, - } -} +// func NewContext( +// networkID uint32, +// blockchainID ids.ID, +// avaxAssetID ids.ID, +// ) Context { +// return &context{ +// networkID: networkID, +// blockchainID: blockchainID, +// avaxAssetID: avaxAssetID, +// } +// } -func (c *context) NetworkID() uint32 { - return c.networkID -} +// func (c *context) NetworkID() uint32 { +// return c.networkID +// } -func (c *context) BlockchainID() ids.ID { - return c.blockchainID -} +// func (c *context) BlockchainID() ids.ID { +// return c.blockchainID +// } -func (c *context) AVAXAssetID() ids.ID { - return c.avaxAssetID -} +// func (c *context) AVAXAssetID() ids.ID { +// return c.avaxAssetID +// } diff --git a/wallet/chain/c/signer.go b/wallet/chain/c/signer.go index 4fd85ed3b532..4bedc378234b 100644 --- a/wallet/chain/c/signer.go +++ b/wallet/chain/c/signer.go @@ -3,221 +3,221 @@ package c -import ( - "errors" - "fmt" - - stdcontext "context" - - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/crypto/keychain" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/hashing" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/components/verify" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" -) - -const version = 0 - -var ( - _ Signer = (*txSigner)(nil) - - errUnknownInputType = errors.New("unknown input type") - errUnknownCredentialType = errors.New("unknown credential type") - errUnknownOutputType = errors.New("unknown output type") - errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") - - emptySig [secp256k1.SignatureLen]byte -) - -type Signer interface { - SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) - SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error -} - -type EthKeychain interface { - // The returned Signer can provide a signature for [addr] - GetEth(addr ethcommon.Address) (keychain.Signer, bool) - // Returns the set of addresses for which the accessor keeps an associated - // signer - EthAddresses() set.Set[ethcommon.Address] -} - -type SignerBackend interface { - GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) -} - -type txSigner struct { - avaxKC keychain.Keychain - ethKC EthKeychain - backend SignerBackend -} - -func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { - return &txSigner{ - avaxKC: avaxKC, - ethKC: ethKC, - backend: backend, - } -} - -func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { - tx := &evm.Tx{UnsignedAtomicTx: utx} - return tx, s.SignAtomic(ctx, tx) -} - -func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { - switch utx := tx.UnsignedAtomicTx.(type) { - case *evm.UnsignedImportTx: - signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) - if err != nil { - return err - } - return sign(tx, true, signers) - case *evm.UnsignedExportTx: - signers := s.getExportSigners(utx.Ins) - return sign(tx, true, signers) - default: - return fmt.Errorf("%w: %T", errUnknownTxType, tx) - } -} - -func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { - txSigners := make([][]keychain.Signer, len(ins)) - for credIndex, transferInput := range ins { - input, ok := transferInput.In.(*secp256k1fx.TransferInput) - if !ok { - return nil, errUnknownInputType - } - - inputSigners := make([]keychain.Signer, len(input.SigIndices)) - txSigners[credIndex] = inputSigners - - utxoID := transferInput.InputID() - utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) - if err == database.ErrNotFound { - // If we don't have access to the UTXO, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - if err != nil { - return nil, err - } - - out, ok := utxo.Out.(*secp256k1fx.TransferOutput) - if !ok { - return nil, errUnknownOutputType - } - - for sigIndex, addrIndex := range input.SigIndices { - if addrIndex >= uint32(len(out.Addrs)) { - return nil, errInvalidUTXOSigIndex - } - - addr := out.Addrs[addrIndex] - key, ok := s.avaxKC.Get(addr) - if !ok { - // If we don't have access to the key, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - inputSigners[sigIndex] = key - } - } - return txSigners, nil -} - -func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { - txSigners := make([][]keychain.Signer, len(ins)) - for credIndex, input := range ins { - inputSigners := make([]keychain.Signer, 1) - txSigners[credIndex] = inputSigners - - key, ok := s.ethKC.GetEth(input.Address) - if !ok { - // If we don't have access to the key, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - inputSigners[0] = key - } - return txSigners -} - -// TODO: remove [signHash] after the ledger supports signing all transactions. -func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { - unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) - if err != nil { - return fmt.Errorf("couldn't marshal unsigned tx: %w", err) - } - unsignedHash := hashing.ComputeHash256(unsignedBytes) - - if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { - tx.Creds = make([]verify.Verifiable, expectedLen) - } - - sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) - for credIndex, inputSigners := range txSigners { - credIntf := tx.Creds[credIndex] - if credIntf == nil { - credIntf = &secp256k1fx.Credential{} - tx.Creds[credIndex] = credIntf - } - - cred, ok := credIntf.(*secp256k1fx.Credential) - if !ok { - return errUnknownCredentialType - } - if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { - cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) - } - - for sigIndex, signer := range inputSigners { - if signer == nil { - // If we don't have access to the key, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - addr := signer.Address() - if sig := cred.Sigs[sigIndex]; sig != emptySig { - // If this signature has already been populated, we can just - // copy the needed signature for the future. - sigCache[addr] = sig - continue - } - - if sig, exists := sigCache[addr]; exists { - // If this key has already produced a signature, we can just - // copy the previous signature. - cred.Sigs[sigIndex] = sig - continue - } - - var sig []byte - if signHash { - sig, err = signer.SignHash(unsignedHash) - } else { - sig, err = signer.Sign(unsignedBytes) - } - if err != nil { - return fmt.Errorf("problem signing tx: %w", err) - } - copy(cred.Sigs[sigIndex][:], sig) - sigCache[addr] = cred.Sigs[sigIndex] - } - } - - signedBytes, err := evm.Codec.Marshal(version, tx) - if err != nil { - return fmt.Errorf("couldn't marshal tx: %w", err) - } - tx.Initialize(unsignedBytes, signedBytes) - return nil -} +// import ( +// "errors" +// "fmt" + +// stdcontext "context" + +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/database" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils/crypto/keychain" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/hashing" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/components/verify" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// ) + +// const version = 0 + +// var ( +// _ Signer = (*txSigner)(nil) + +// errUnknownInputType = errors.New("unknown input type") +// errUnknownCredentialType = errors.New("unknown credential type") +// errUnknownOutputType = errors.New("unknown output type") +// errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") + +// emptySig [secp256k1.SignatureLen]byte +// ) + +// type Signer interface { +// SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) +// SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error +// } + +// type EthKeychain interface { +// // The returned Signer can provide a signature for [addr] +// GetEth(addr ethcommon.Address) (keychain.Signer, bool) +// // Returns the set of addresses for which the accessor keeps an associated +// // signer +// EthAddresses() set.Set[ethcommon.Address] +// } + +// type SignerBackend interface { +// GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) +// } + +// type txSigner struct { +// avaxKC keychain.Keychain +// ethKC EthKeychain +// backend SignerBackend +// } + +// func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { +// return &txSigner{ +// avaxKC: avaxKC, +// ethKC: ethKC, +// backend: backend, +// } +// } + +// func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { +// tx := &evm.Tx{UnsignedAtomicTx: utx} +// return tx, s.SignAtomic(ctx, tx) +// } + +// func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { +// switch utx := tx.UnsignedAtomicTx.(type) { +// case *evm.UnsignedImportTx: +// signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) +// if err != nil { +// return err +// } +// return sign(tx, true, signers) +// case *evm.UnsignedExportTx: +// signers := s.getExportSigners(utx.Ins) +// return sign(tx, true, signers) +// default: +// return fmt.Errorf("%w: %T", errUnknownTxType, tx) +// } +// } + +// func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { +// txSigners := make([][]keychain.Signer, len(ins)) +// for credIndex, transferInput := range ins { +// input, ok := transferInput.In.(*secp256k1fx.TransferInput) +// if !ok { +// return nil, errUnknownInputType +// } + +// inputSigners := make([]keychain.Signer, len(input.SigIndices)) +// txSigners[credIndex] = inputSigners + +// utxoID := transferInput.InputID() +// utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) +// if err == database.ErrNotFound { +// // If we don't have access to the UTXO, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// if err != nil { +// return nil, err +// } + +// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) +// if !ok { +// return nil, errUnknownOutputType +// } + +// for sigIndex, addrIndex := range input.SigIndices { +// if addrIndex >= uint32(len(out.Addrs)) { +// return nil, errInvalidUTXOSigIndex +// } + +// addr := out.Addrs[addrIndex] +// key, ok := s.avaxKC.Get(addr) +// if !ok { +// // If we don't have access to the key, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// inputSigners[sigIndex] = key +// } +// } +// return txSigners, nil +// } + +// func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { +// txSigners := make([][]keychain.Signer, len(ins)) +// for credIndex, input := range ins { +// inputSigners := make([]keychain.Signer, 1) +// txSigners[credIndex] = inputSigners + +// key, ok := s.ethKC.GetEth(input.Address) +// if !ok { +// // If we don't have access to the key, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// inputSigners[0] = key +// } +// return txSigners +// } + +// // TODO: remove [signHash] after the ledger supports signing all transactions. +// func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { +// unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) +// if err != nil { +// return fmt.Errorf("couldn't marshal unsigned tx: %w", err) +// } +// unsignedHash := hashing.ComputeHash256(unsignedBytes) + +// if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { +// tx.Creds = make([]verify.Verifiable, expectedLen) +// } + +// sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) +// for credIndex, inputSigners := range txSigners { +// credIntf := tx.Creds[credIndex] +// if credIntf == nil { +// credIntf = &secp256k1fx.Credential{} +// tx.Creds[credIndex] = credIntf +// } + +// cred, ok := credIntf.(*secp256k1fx.Credential) +// if !ok { +// return errUnknownCredentialType +// } +// if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { +// cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) +// } + +// for sigIndex, signer := range inputSigners { +// if signer == nil { +// // If we don't have access to the key, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// addr := signer.Address() +// if sig := cred.Sigs[sigIndex]; sig != emptySig { +// // If this signature has already been populated, we can just +// // copy the needed signature for the future. +// sigCache[addr] = sig +// continue +// } + +// if sig, exists := sigCache[addr]; exists { +// // If this key has already produced a signature, we can just +// // copy the previous signature. +// cred.Sigs[sigIndex] = sig +// continue +// } + +// var sig []byte +// if signHash { +// sig, err = signer.SignHash(unsignedHash) +// } else { +// sig, err = signer.Sign(unsignedBytes) +// } +// if err != nil { +// return fmt.Errorf("problem signing tx: %w", err) +// } +// copy(cred.Sigs[sigIndex][:], sig) +// sigCache[addr] = cred.Sigs[sigIndex] +// } +// } + +// signedBytes, err := evm.Codec.Marshal(version, tx) +// if err != nil { +// return fmt.Errorf("couldn't marshal tx: %w", err) +// } +// tx.Initialize(unsignedBytes, signedBytes) +// return nil +// } diff --git a/wallet/chain/c/wallet.go b/wallet/chain/c/wallet.go index fb1a83d53dad..ebee50a9a958 100644 --- a/wallet/chain/c/wallet.go +++ b/wallet/chain/c/wallet.go @@ -3,204 +3,204 @@ package c -import ( - "errors" - "math/big" - "time" - - "github.com/ava-labs/coreth/ethclient" - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var ( - _ Wallet = (*wallet)(nil) - - errNotCommitted = errors.New("not committed") -) - -type Wallet interface { - Context - - // Builder returns the builder that will be used to create the transactions. - Builder() Builder - - // Signer returns the signer that will be used to sign the transactions. - Signer() Signer - - // IssueImportTx creates, signs, and issues an import transaction that - // attempts to consume all the available UTXOs and import the funds to [to]. - // - // - [chainID] specifies the chain to be importing funds from. - // - [to] specifies where to send the imported funds to. - IssueImportTx( - chainID ids.ID, - to ethcommon.Address, - options ...common.Option, - ) (*evm.Tx, error) - - // IssueExportTx creates, signs, and issues an export transaction that - // attempts to send all the provided [outputs] to the requested [chainID]. - // - // - [chainID] specifies the chain to be exporting the funds to. - // - [outputs] specifies the outputs to send to the [chainID]. - IssueExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - options ...common.Option, - ) (*evm.Tx, error) - - // IssueUnsignedTx signs and issues the unsigned tx. - IssueUnsignedAtomicTx( - utx evm.UnsignedAtomicTx, - options ...common.Option, - ) (*evm.Tx, error) - - // IssueAtomicTx issues the signed tx. - IssueAtomicTx( - tx *evm.Tx, - options ...common.Option, - ) error -} - -func NewWallet( - builder Builder, - signer Signer, - avaxClient evm.Client, - ethClient ethclient.Client, - backend Backend, -) Wallet { - return &wallet{ - Backend: backend, - builder: builder, - signer: signer, - avaxClient: avaxClient, - ethClient: ethClient, - } -} - -type wallet struct { - Backend - builder Builder - signer Signer - avaxClient evm.Client - ethClient ethclient.Client -} - -func (w *wallet) Builder() Builder { - return w.builder -} - -func (w *wallet) Signer() Signer { - return w.signer -} - -func (w *wallet) IssueImportTx( - chainID ids.ID, - to ethcommon.Address, - options ...common.Option, -) (*evm.Tx, error) { - baseFee, err := w.baseFee(options) - if err != nil { - return nil, err - } - - utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) - if err != nil { - return nil, err - } - return w.IssueUnsignedAtomicTx(utx, options...) -} - -func (w *wallet) IssueExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - options ...common.Option, -) (*evm.Tx, error) { - baseFee, err := w.baseFee(options) - if err != nil { - return nil, err - } - - utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) - if err != nil { - return nil, err - } - return w.IssueUnsignedAtomicTx(utx, options...) -} - -func (w *wallet) IssueUnsignedAtomicTx( - utx evm.UnsignedAtomicTx, - options ...common.Option, -) (*evm.Tx, error) { - ops := common.NewOptions(options) - ctx := ops.Context() - tx, err := w.signer.SignUnsignedAtomic(ctx, utx) - if err != nil { - return nil, err - } - - return tx, w.IssueAtomicTx(tx, options...) -} - -func (w *wallet) IssueAtomicTx( - tx *evm.Tx, - options ...common.Option, -) error { - ops := common.NewOptions(options) - ctx := ops.Context() - txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) - if err != nil { - return err - } - - if f := ops.PostIssuanceFunc(); f != nil { - f(txID) - } - - if ops.AssumeDecided() { - return w.Backend.AcceptAtomicTx(ctx, tx) - } - - pollFrequency := ops.PollFrequency() - ticker := time.NewTicker(pollFrequency) - defer ticker.Stop() - - for { - status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) - if err != nil { - return err - } - - switch status { - case evm.Accepted: - return w.Backend.AcceptAtomicTx(ctx, tx) - case evm.Dropped, evm.Unknown: - return errNotCommitted - } - - // The tx is Processing. - - select { - case <-ticker.C: - case <-ctx.Done(): - return ctx.Err() - } - } -} - -func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { - ops := common.NewOptions(options) - baseFee := ops.BaseFee(nil) - if baseFee != nil { - return baseFee, nil - } - - ctx := ops.Context() - return w.ethClient.EstimateBaseFee(ctx) -} +// import ( +// "errors" +// "math/big" +// "time" + +// "github.com/ava-labs/coreth/ethclient" +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var ( +// _ Wallet = (*wallet)(nil) + +// errNotCommitted = errors.New("not committed") +// ) + +// type Wallet interface { +// Context + +// // Builder returns the builder that will be used to create the transactions. +// Builder() Builder + +// // Signer returns the signer that will be used to sign the transactions. +// Signer() Signer + +// // IssueImportTx creates, signs, and issues an import transaction that +// // attempts to consume all the available UTXOs and import the funds to [to]. +// // +// // - [chainID] specifies the chain to be importing funds from. +// // - [to] specifies where to send the imported funds to. +// IssueImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// options ...common.Option, +// ) (*evm.Tx, error) + +// // IssueExportTx creates, signs, and issues an export transaction that +// // attempts to send all the provided [outputs] to the requested [chainID]. +// // +// // - [chainID] specifies the chain to be exporting the funds to. +// // - [outputs] specifies the outputs to send to the [chainID]. +// IssueExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// options ...common.Option, +// ) (*evm.Tx, error) + +// // IssueUnsignedTx signs and issues the unsigned tx. +// IssueUnsignedAtomicTx( +// utx evm.UnsignedAtomicTx, +// options ...common.Option, +// ) (*evm.Tx, error) + +// // IssueAtomicTx issues the signed tx. +// IssueAtomicTx( +// tx *evm.Tx, +// options ...common.Option, +// ) error +// } + +// func NewWallet( +// builder Builder, +// signer Signer, +// avaxClient evm.Client, +// ethClient ethclient.Client, +// backend Backend, +// ) Wallet { +// return &wallet{ +// Backend: backend, +// builder: builder, +// signer: signer, +// avaxClient: avaxClient, +// ethClient: ethClient, +// } +// } + +// type wallet struct { +// Backend +// builder Builder +// signer Signer +// avaxClient evm.Client +// ethClient ethclient.Client +// } + +// func (w *wallet) Builder() Builder { +// return w.builder +// } + +// func (w *wallet) Signer() Signer { +// return w.signer +// } + +// func (w *wallet) IssueImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// options ...common.Option, +// ) (*evm.Tx, error) { +// baseFee, err := w.baseFee(options) +// if err != nil { +// return nil, err +// } + +// utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) +// if err != nil { +// return nil, err +// } +// return w.IssueUnsignedAtomicTx(utx, options...) +// } + +// func (w *wallet) IssueExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// options ...common.Option, +// ) (*evm.Tx, error) { +// baseFee, err := w.baseFee(options) +// if err != nil { +// return nil, err +// } + +// utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) +// if err != nil { +// return nil, err +// } +// return w.IssueUnsignedAtomicTx(utx, options...) +// } + +// func (w *wallet) IssueUnsignedAtomicTx( +// utx evm.UnsignedAtomicTx, +// options ...common.Option, +// ) (*evm.Tx, error) { +// ops := common.NewOptions(options) +// ctx := ops.Context() +// tx, err := w.signer.SignUnsignedAtomic(ctx, utx) +// if err != nil { +// return nil, err +// } + +// return tx, w.IssueAtomicTx(tx, options...) +// } + +// func (w *wallet) IssueAtomicTx( +// tx *evm.Tx, +// options ...common.Option, +// ) error { +// ops := common.NewOptions(options) +// ctx := ops.Context() +// txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) +// if err != nil { +// return err +// } + +// if f := ops.PostIssuanceFunc(); f != nil { +// f(txID) +// } + +// if ops.AssumeDecided() { +// return w.Backend.AcceptAtomicTx(ctx, tx) +// } + +// pollFrequency := ops.PollFrequency() +// ticker := time.NewTicker(pollFrequency) +// defer ticker.Stop() + +// for { +// status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) +// if err != nil { +// return err +// } + +// switch status { +// case evm.Accepted: +// return w.Backend.AcceptAtomicTx(ctx, tx) +// case evm.Dropped, evm.Unknown: +// return errNotCommitted +// } + +// // The tx is Processing. + +// select { +// case <-ticker.C: +// case <-ctx.Done(): +// return ctx.Err() +// } +// } +// } + +// func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { +// ops := common.NewOptions(options) +// baseFee := ops.BaseFee(nil) +// if baseFee != nil { +// return baseFee, nil +// } + +// ctx := ops.Context() +// return w.ethClient.EstimateBaseFee(ctx) +// } diff --git a/wallet/chain/c/wallet_with_options.go b/wallet/chain/c/wallet_with_options.go index 7d6193683d49..fd69a6d4fd02 100644 --- a/wallet/chain/c/wallet_with_options.go +++ b/wallet/chain/c/wallet_with_options.go @@ -3,80 +3,80 @@ package c -import ( - "github.com/ava-labs/coreth/plugin/evm" +// import ( +// "github.com/ava-labs/coreth/plugin/evm" - ethcommon "github.com/ethereum/go-ethereum/common" +// ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) -var _ Wallet = (*walletWithOptions)(nil) +// var _ Wallet = (*walletWithOptions)(nil) -func NewWalletWithOptions( - wallet Wallet, - options ...common.Option, -) Wallet { - return &walletWithOptions{ - Wallet: wallet, - options: options, - } -} +// func NewWalletWithOptions( +// wallet Wallet, +// options ...common.Option, +// ) Wallet { +// return &walletWithOptions{ +// Wallet: wallet, +// options: options, +// } +// } -type walletWithOptions struct { - Wallet - options []common.Option -} +// type walletWithOptions struct { +// Wallet +// options []common.Option +// } -func (w *walletWithOptions) Builder() Builder { - return NewBuilderWithOptions( - w.Wallet.Builder(), - w.options..., - ) -} +// func (w *walletWithOptions) Builder() Builder { +// return NewBuilderWithOptions( +// w.Wallet.Builder(), +// w.options..., +// ) +// } -func (w *walletWithOptions) IssueImportTx( - chainID ids.ID, - to ethcommon.Address, - options ...common.Option, -) (*evm.Tx, error) { - return w.Wallet.IssueImportTx( - chainID, - to, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// options ...common.Option, +// ) (*evm.Tx, error) { +// return w.Wallet.IssueImportTx( +// chainID, +// to, +// common.UnionOptions(w.options, options)..., +// ) +// } -func (w *walletWithOptions) IssueExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - options ...common.Option, -) (*evm.Tx, error) { - return w.Wallet.IssueExportTx( - chainID, - outputs, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// options ...common.Option, +// ) (*evm.Tx, error) { +// return w.Wallet.IssueExportTx( +// chainID, +// outputs, +// common.UnionOptions(w.options, options)..., +// ) +// } -func (w *walletWithOptions) IssueUnsignedAtomicTx( - utx evm.UnsignedAtomicTx, - options ...common.Option, -) (*evm.Tx, error) { - return w.Wallet.IssueUnsignedAtomicTx( - utx, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueUnsignedAtomicTx( +// utx evm.UnsignedAtomicTx, +// options ...common.Option, +// ) (*evm.Tx, error) { +// return w.Wallet.IssueUnsignedAtomicTx( +// utx, +// common.UnionOptions(w.options, options)..., +// ) +// } -func (w *walletWithOptions) IssueAtomicTx( - tx *evm.Tx, - options ...common.Option, -) error { - return w.Wallet.IssueAtomicTx( - tx, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueAtomicTx( +// tx *evm.Tx, +// options ...common.Option, +// ) error { +// return w.Wallet.IssueAtomicTx( +// tx, +// common.UnionOptions(w.options, options)..., +// ) +// } diff --git a/wallet/subnet/primary/api.go b/wallet/subnet/primary/api.go index 3ac72c217884..3d35fee24e4d 100644 --- a/wallet/subnet/primary/api.go +++ b/wallet/subnet/primary/api.go @@ -5,12 +5,12 @@ package primary import ( "context" - "fmt" + // "fmt" - "github.com/ava-labs/coreth/ethclient" - "github.com/ava-labs/coreth/plugin/evm" + // "github.com/ava-labs/coreth/ethclient" + // "github.com/ava-labs/coreth/plugin/evm" - "github.com/ethereum/go-ethereum/common" + // "github.com/ethereum/go-ethereum/common" "github.com/ava-labs/avalanchego/api/info" "github.com/ava-labs/avalanchego/codec" @@ -22,7 +22,8 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm" "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/wallet/chain/c" + + // "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" ) @@ -59,9 +60,9 @@ type AVAXState struct { PCTX p.Context XClient avm.Client XCTX x.Context - CClient evm.Client - CCTX c.Context - UTXOs UTXOs + // CClient evm.Client + // CCTX c.Context + UTXOs UTXOs } func FetchState( @@ -75,7 +76,7 @@ func FetchState( infoClient := info.NewClient(uri) pClient := platformvm.NewClient(uri) xClient := avm.NewClient(uri, "X") - cClient := evm.NewCChainClient(uri) + // cClient := evm.NewCChainClient(uri) pCTX, err := p.NewContextFromClients(ctx, infoClient, xClient) if err != nil { @@ -87,10 +88,10 @@ func FetchState( return nil, err } - cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) - if err != nil { - return nil, err - } + // cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) + // if err != nil { + // return nil, err + // } utxos := NewUTXOs() addrList := addrs.List() @@ -109,11 +110,11 @@ func FetchState( client: xClient, codec: x.Parser.Codec(), }, - { - id: cCTX.BlockchainID(), - client: cClient, - codec: evm.Codec, - }, + // { + // id: cCTX.BlockchainID(), + // client: cClient, + // codec: evm.Codec, + // }, } for _, destinationChain := range chains { for _, sourceChain := range chains { @@ -136,52 +137,52 @@ func FetchState( PCTX: pCTX, XClient: xClient, XCTX: xCTX, - CClient: cClient, - CCTX: cCTX, - UTXOs: utxos, + // CClient: cClient, + // CCTX: cCTX, + UTXOs: utxos, }, nil } -type EthState struct { - Client ethclient.Client - Accounts map[common.Address]*c.Account -} - -func FetchEthState( - ctx context.Context, - uri string, - addrs set.Set[common.Address], -) (*EthState, error) { - path := fmt.Sprintf( - "%s/ext/%s/C/rpc", - uri, - constants.ChainAliasPrefix, - ) - client, err := ethclient.Dial(path) - if err != nil { - return nil, err - } - - accounts := make(map[common.Address]*c.Account, addrs.Len()) - for addr := range addrs { - balance, err := client.BalanceAt(ctx, addr, nil) - if err != nil { - return nil, err - } - nonce, err := client.NonceAt(ctx, addr, nil) - if err != nil { - return nil, err - } - accounts[addr] = &c.Account{ - Balance: balance, - Nonce: nonce, - } - } - return &EthState{ - Client: client, - Accounts: accounts, - }, nil -} +// type EthState struct { +// Client ethclient.Client +// Accounts map[common.Address]*c.Account +// } + +// func FetchEthState( +// ctx context.Context, +// uri string, +// addrs set.Set[common.Address], +// ) (*EthState, error) { +// path := fmt.Sprintf( +// "%s/ext/%s/C/rpc", +// uri, +// constants.ChainAliasPrefix, +// ) +// client, err := ethclient.Dial(path) +// if err != nil { +// return nil, err +// } + +// accounts := make(map[common.Address]*c.Account, addrs.Len()) +// for addr := range addrs { +// balance, err := client.BalanceAt(ctx, addr, nil) +// if err != nil { +// return nil, err +// } +// nonce, err := client.NonceAt(ctx, addr, nil) +// if err != nil { +// return nil, err +// } +// accounts[addr] = &c.Account{ +// Balance: balance, +// Nonce: nonce, +// } +// } +// return &EthState{ +// Client: client, +// Accounts: accounts, +// }, nil +// } // AddAllUTXOs fetches all the UTXOs referenced by [addresses] that were sent // from [sourceChainID] to [destinationChainID] from the [client]. It then uses diff --git a/wallet/subnet/primary/example_test.go b/wallet/subnet/primary/example_test.go index 483c049d4ac0..4a73e8c070b2 100644 --- a/wallet/subnet/primary/example_test.go +++ b/wallet/subnet/primary/example_test.go @@ -30,7 +30,7 @@ func ExampleWallet() { wallet, err := MakeWallet(ctx, &WalletConfig{ URI: LocalAPIURI, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet with: %s\n", err) diff --git a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go index d5e8ce422307..21c081d2982b 100644 --- a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go @@ -46,9 +46,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/add-primary-validator/main.go b/wallet/subnet/primary/examples/add-primary-validator/main.go index a56dae23db3a..13c28f995f63 100644 --- a/wallet/subnet/primary/examples/add-primary-validator/main.go +++ b/wallet/subnet/primary/examples/add-primary-validator/main.go @@ -45,7 +45,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/c-chain-export/main.go b/wallet/subnet/primary/examples/c-chain-export/main.go index fec55c899feb..a6b9a0c810b8 100644 --- a/wallet/subnet/primary/examples/c-chain-export/main.go +++ b/wallet/subnet/primary/examples/c-chain-export/main.go @@ -3,70 +3,70 @@ package main -import ( - "context" - "log" - "time" +// import ( +// "context" +// "log" +// "time" - "github.com/ava-labs/avalanchego/genesis" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary" -) +// "github.com/ava-labs/avalanchego/genesis" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary" +// ) -func main() { - key := genesis.EWOQKey - uri := primary.LocalAPIURI - kc := secp256k1fx.NewKeychain(key) - avaxAddr := key.Address() +// func main() { +// key := genesis.EWOQKey +// uri := primary.LocalAPIURI +// kc := secp256k1fx.NewKeychain(key) +// avaxAddr := key.Address() - ctx := context.Background() +// ctx := context.Background() - // MakeWallet fetches the available UTXOs owned by [kc] on the network that - // [uri] is hosting. - walletSyncStartTime := time.Now() - wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, - }) - if err != nil { - log.Fatalf("failed to initialize wallet: %s\n", err) - } - log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) +// // MakeWallet fetches the available UTXOs owned by [kc] on the network that +// // [uri] is hosting. +// walletSyncStartTime := time.Now() +// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ +// URI: uri, +// AVAXKeychain: kc, +// EthKeychain: kc, +// }) +// if err != nil { +// log.Fatalf("failed to initialize wallet: %s\n", err) +// } +// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) - // Get the P-chain wallet - pWallet := wallet.P() - cWallet := wallet.C() +// // Get the P-chain wallet +// pWallet := wallet.P() +// cWallet := wallet.C() - // Pull out useful constants to use when issuing transactions. - cChainID := cWallet.BlockchainID() - owner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - avaxAddr, - }, - } +// // Pull out useful constants to use when issuing transactions. +// cChainID := cWallet.BlockchainID() +// owner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// avaxAddr, +// }, +// } - exportStartTime := time.Now() - exportTx, err := cWallet.IssueExportTx( - constants.PlatformChainID, - []*secp256k1fx.TransferOutput{{ - Amt: units.Avax, - OutputOwners: owner, - }}, - ) - if err != nil { - log.Fatalf("failed to issue export transaction: %s\n", err) - } - log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) +// exportStartTime := time.Now() +// exportTx, err := cWallet.IssueExportTx( +// constants.PlatformChainID, +// []*secp256k1fx.TransferOutput{{ +// Amt: units.Avax, +// OutputOwners: owner, +// }}, +// ) +// if err != nil { +// log.Fatalf("failed to issue export transaction: %s\n", err) +// } +// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) - importStartTime := time.Now() - importTx, err := pWallet.IssueImportTx(cChainID, &owner) - if err != nil { - log.Fatalf("failed to issue import transaction: %s\n", err) - } - log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) -} +// importStartTime := time.Now() +// importTx, err := pWallet.IssueImportTx(cChainID, &owner) +// if err != nil { +// log.Fatalf("failed to issue import transaction: %s\n", err) +// } +// log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) +// } diff --git a/wallet/subnet/primary/examples/c-chain-import/main.go b/wallet/subnet/primary/examples/c-chain-import/main.go index b4dc4e603eb3..2d9b8a244cb0 100644 --- a/wallet/subnet/primary/examples/c-chain-import/main.go +++ b/wallet/subnet/primary/examples/c-chain-import/main.go @@ -3,75 +3,75 @@ package main -import ( - "context" - "log" - "time" +// import ( +// "context" +// "log" +// "time" - "github.com/ava-labs/coreth/plugin/evm" +// "github.com/ava-labs/coreth/plugin/evm" - "github.com/ava-labs/avalanchego/genesis" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary" -) +// "github.com/ava-labs/avalanchego/genesis" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary" +// ) -func main() { - key := genesis.EWOQKey - uri := primary.LocalAPIURI - kc := secp256k1fx.NewKeychain(key) - avaxAddr := key.Address() - ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) +// func main() { +// key := genesis.EWOQKey +// uri := primary.LocalAPIURI +// kc := secp256k1fx.NewKeychain(key) +// avaxAddr := key.Address() +// ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) - ctx := context.Background() +// ctx := context.Background() - // MakeWallet fetches the available UTXOs owned by [kc] on the network that - // [uri] is hosting. - walletSyncStartTime := time.Now() - wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, - }) - if err != nil { - log.Fatalf("failed to initialize wallet: %s\n", err) - } - log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) +// // MakeWallet fetches the available UTXOs owned by [kc] on the network that +// // [uri] is hosting. +// walletSyncStartTime := time.Now() +// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ +// URI: uri, +// AVAXKeychain: kc, +// EthKeychain: kc, +// }) +// if err != nil { +// log.Fatalf("failed to initialize wallet: %s\n", err) +// } +// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) - // Get the P-chain wallet - pWallet := wallet.P() - cWallet := wallet.C() +// // Get the P-chain wallet +// pWallet := wallet.P() +// cWallet := wallet.C() - // Pull out useful constants to use when issuing transactions. - cChainID := cWallet.BlockchainID() - avaxAssetID := cWallet.AVAXAssetID() - owner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - avaxAddr, - }, - } +// // Pull out useful constants to use when issuing transactions. +// cChainID := cWallet.BlockchainID() +// avaxAssetID := cWallet.AVAXAssetID() +// owner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// avaxAddr, +// }, +// } - exportStartTime := time.Now() - exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ - Asset: avax.Asset{ID: avaxAssetID}, - Out: &secp256k1fx.TransferOutput{ - Amt: units.Avax, - OutputOwners: owner, - }, - }}) - if err != nil { - log.Fatalf("failed to issue export transaction: %s\n", err) - } - log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) +// exportStartTime := time.Now() +// exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ +// Asset: avax.Asset{ID: avaxAssetID}, +// Out: &secp256k1fx.TransferOutput{ +// Amt: units.Avax, +// OutputOwners: owner, +// }, +// }}) +// if err != nil { +// log.Fatalf("failed to issue export transaction: %s\n", err) +// } +// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) - importStartTime := time.Now() - importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) - if err != nil { - log.Fatalf("failed to issue import transaction: %s\n", err) - } - log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) -} +// importStartTime := time.Now() +// importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) +// if err != nil { +// log.Fatalf("failed to issue import transaction: %s\n", err) +// } +// log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) +// } diff --git a/wallet/subnet/primary/examples/create-asset/main.go b/wallet/subnet/primary/examples/create-asset/main.go index 30804f083df6..0bccfbb5fc52 100644 --- a/wallet/subnet/primary/examples/create-asset/main.go +++ b/wallet/subnet/primary/examples/create-asset/main.go @@ -30,7 +30,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-chain/main.go b/wallet/subnet/primary/examples/create-chain/main.go index 5e6898a1b649..521a3cca53cf 100644 --- a/wallet/subnet/primary/examples/create-chain/main.go +++ b/wallet/subnet/primary/examples/create-chain/main.go @@ -41,9 +41,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/create-locked-stakeable/main.go b/wallet/subnet/primary/examples/create-locked-stakeable/main.go index e688968e9e8a..92f1b5cb0e1b 100644 --- a/wallet/subnet/primary/examples/create-locked-stakeable/main.go +++ b/wallet/subnet/primary/examples/create-locked-stakeable/main.go @@ -39,7 +39,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-subnet/main.go b/wallet/subnet/primary/examples/create-subnet/main.go index add98ea7931c..3e8d69bc016a 100644 --- a/wallet/subnet/primary/examples/create-subnet/main.go +++ b/wallet/subnet/primary/examples/create-subnet/main.go @@ -28,7 +28,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/remove-subnet-validator/main.go b/wallet/subnet/primary/examples/remove-subnet-validator/main.go index 2842c7c0a790..46f4b85124db 100644 --- a/wallet/subnet/primary/examples/remove-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/remove-subnet-validator/main.go @@ -38,9 +38,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/wallet.go b/wallet/subnet/primary/wallet.go index 54de390d029c..ae5e4202a099 100644 --- a/wallet/subnet/primary/wallet.go +++ b/wallet/subnet/primary/wallet.go @@ -11,7 +11,8 @@ import ( "github.com/ava-labs/avalanchego/utils/crypto/keychain" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/wallet/chain/c" + + // "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" @@ -23,13 +24,13 @@ var _ Wallet = (*wallet)(nil) type Wallet interface { P() p.Wallet X() x.Wallet - C() c.Wallet + // C() c.Wallet } type wallet struct { p p.Wallet x x.Wallet - c c.Wallet + // c c.Wallet } func (w *wallet) P() p.Wallet { @@ -40,16 +41,16 @@ func (w *wallet) X() x.Wallet { return w.x } -func (w *wallet) C() c.Wallet { - return w.c -} +// func (w *wallet) C() c.Wallet { +// return w.c +// } // Creates a new default wallet -func NewWallet(p p.Wallet, x x.Wallet, c c.Wallet) Wallet { +func NewWallet(p p.Wallet, x x.Wallet /*, c c.Wallet*/) Wallet { return &wallet{ p: p, x: x, - c: c, + // c: c, } } @@ -58,7 +59,7 @@ func NewWalletWithOptions(w Wallet, options ...common.Option) Wallet { return NewWallet( p.NewWalletWithOptions(w.P(), options...), x.NewWalletWithOptions(w.X(), options...), - c.NewWalletWithOptions(w.C(), options...), + // c.NewWalletWithOptions(w.C(), options...), ) } @@ -67,7 +68,7 @@ type WalletConfig struct { URI string // required // Keys to use for signing all transactions. AVAXKeychain keychain.Keychain // required - EthKeychain c.EthKeychain // required + // EthKeychain c.EthKeychain // required // Set of P-chain transactions that the wallet should know about to be able // to generate transactions. PChainTxs map[ids.ID]*txs.Tx // optional @@ -93,11 +94,11 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { return nil, err } - ethAddrs := config.EthKeychain.EthAddresses() - ethState, err := FetchEthState(ctx, config.URI, ethAddrs) - if err != nil { - return nil, err - } + // ethAddrs := config.EthKeychain.EthAddresses() + // ethState, err := FetchEthState(ctx, config.URI, ethAddrs) + // if err != nil { + // return nil, err + // } pChainTxs := config.PChainTxs if pChainTxs == nil { @@ -127,15 +128,15 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { xBuilder := x.NewBuilder(avaxAddrs, xBackend) xSigner := x.NewSigner(config.AVAXKeychain, xBackend) - cChainID := avaxState.CCTX.BlockchainID() - cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) - cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) - cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) - cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) + // cChainID := avaxState.CCTX.BlockchainID() + // cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) + // cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) + // cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) + // cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) return NewWallet( p.NewWallet(pBuilder, pSigner, avaxState.PClient, pBackend), x.NewWallet(xBuilder, xSigner, avaxState.XClient, xBackend), - c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), + // c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), ), nil } From c8ec0f239781d009dbe43f5c97631f95d67780fa Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 30 Oct 2023 11:58:47 +0100 Subject: [PATCH 11/36] bumped coreth version --- go.mod | 25 + go.sum | 76 ++ node/node.go | 4 +- snow/engine/snowman/transitive.go | 17 +- tests/e2e/c/dynamic_fees.go | 328 ++++---- tests/e2e/c/interchain_workflow.go | 322 +++---- tests/e2e/e2e.go | 124 ++- tests/e2e/p/interchain_workflow.go | 446 +++++----- tests/e2e/x/interchain_workflow.go | 298 +++---- tests/fixture/testnet/config.go | 56 +- vms/example/xsvm/cmd/chain/create/cmd.go | 6 +- wallet/chain/c/backend.go | 300 +++---- wallet/chain/c/builder.go | 792 +++++++++--------- wallet/chain/c/builder_with_options.go | 136 +-- wallet/chain/c/context.go | 130 +-- wallet/chain/c/signer.go | 436 +++++----- wallet/chain/c/wallet.go | 402 ++++----- wallet/chain/c/wallet_with_options.go | 134 +-- wallet/subnet/primary/api.go | 123 ++- wallet/subnet/primary/example_test.go | 2 +- .../add-permissioned-subnet-validator/main.go | 6 +- .../examples/add-primary-validator/main.go | 2 +- .../primary/examples/c-chain-export/main.go | 118 +-- .../primary/examples/c-chain-import/main.go | 126 +-- .../primary/examples/create-asset/main.go | 2 +- .../primary/examples/create-chain/main.go | 6 +- .../examples/create-locked-stakeable/main.go | 2 +- .../primary/examples/create-subnet/main.go | 2 +- .../examples/remove-subnet-validator/main.go | 6 +- wallet/subnet/primary/wallet.go | 43 +- 30 files changed, 2285 insertions(+), 2185 deletions(-) diff --git a/go.mod b/go.mod index 40d59d0cb294..df21e176edb6 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/DataDog/zstd v1.5.2 github.com/Microsoft/go-winio v0.5.2 github.com/NYTimes/gziphandler v1.1.1 + github.com/ava-labs/coreth v0.12.7-0.20231030104939-abfd81202a00 github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 github.com/btcsuite/btcd/btcutil v1.1.3 github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 @@ -71,6 +72,7 @@ require ( require ( github.com/BurntSushi/toml v1.2.1 // indirect + github.com/VictoriaMetrics/fastcache v1.10.0 // indirect github.com/benbjohnson/clock v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect @@ -79,26 +81,44 @@ require ( github.com/cockroachdb/errors v1.9.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/redact v1.1.3 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set/v2 v2.1.0 // indirect + github.com/dlclark/regexp2 v1.7.0 // indirect + github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect + github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/frankban/quicktest v1.14.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect + github.com/go-stack/stack v1.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/go-cmp v0.5.9 // indirect + github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 // indirect + github.com/hashicorp/go-bexpr v0.1.10 // indirect + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/klauspost/compress v1.15.15 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/magiconair/properties v1.8.6 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mitchellh/pointerstructure v1.2.0 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect @@ -106,12 +126,17 @@ require ( github.com/prometheus/common v0.39.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sanity-io/litter v1.5.1 // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/status-im/keycard-go v0.2.0 // indirect github.com/subosito/gotenv v1.3.0 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/zondax/hid v0.9.1 // indirect github.com/zondax/ledger-go v0.14.1 // indirect diff --git a/go.sum b/go.sum index 09e5526b3f20..9d439e898a88 100644 --- a/go.sum +++ b/go.sum @@ -52,12 +52,18 @@ github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cq github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= +github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY= +github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/ava-labs/coreth v0.12.7-0.20231030104939-abfd81202a00 h1:YNwaqnihOFx61sO1DEPvv0oXnMSKsZxKYGBzy9vspNU= +github.com/ava-labs/coreth v0.12.7-0.20231030104939-abfd81202a00/go.mod h1:b9c2YqasbKmAJMN+56n0bFO0wSJuBVLmZ4KETxPGeUI= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 h1:EdxD90j5sClfL5Ngpz2TlnbnkNYdFPDXa0jDOjam65c= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7/go.mod h1:XhiXSrh90sHUbkERzaxEftCmUz53eCijshDLZ4fByVM= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= @@ -94,13 +100,18 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -130,12 +141,16 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= +github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= @@ -146,6 +161,14 @@ github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6ps github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= +github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= +github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= +github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -162,6 +185,8 @@ github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2 github.com/ethereum/go-ethereum v1.12.0/go.mod h1:/oo2X/dZLJjf2mJ6YT9wcWxa4nNJDBKDBU6sFIpx1Gs= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -170,6 +195,8 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= @@ -193,7 +220,11 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= @@ -278,10 +309,14 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -302,11 +337,17 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 h1:kr3j8iIMR4ywO/O0rvksXaJvauGGCMg2zAZIiNZ9uIQ= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0/go.mod h1:ummNFgdgLhhX7aIiy35vVmQNS0rWXknfPE0qe6fmFXg= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw= +github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e/go.mod h1:j9cQbcqHQujT0oKJ38PylVfqohClLr3CvDC+Qcg+lhU= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8= @@ -318,6 +359,7 @@ github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3 github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -359,6 +401,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -366,6 +409,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= @@ -376,11 +420,17 @@ github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -389,8 +439,11 @@ github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -409,6 +462,8 @@ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -476,6 +531,8 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sanity-io/litter v1.5.1 h1:dwnrSypP6q56o3lFxTU+t2fwQ9A+U5qrXVO4Qg9KwVU= github.com/sanity-io/litter v1.5.1/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0= @@ -511,6 +568,8 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= +github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -540,10 +599,14 @@ github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITn github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= +github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -555,6 +618,8 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1: github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= @@ -564,6 +629,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= @@ -661,6 +727,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -706,6 +773,7 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -729,6 +797,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -793,8 +862,12 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -811,6 +884,7 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -874,6 +948,7 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -998,6 +1073,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= diff --git a/node/node.go b/node/node.go index 9e72b7dcc450..4200a33699ab 100644 --- a/node/node.go +++ b/node/node.go @@ -24,7 +24,7 @@ import ( "go.uber.org/zap" - // coreth "github.com/ava-labs/coreth/plugin/evm" + coreth "github.com/ava-labs/coreth/plugin/evm" "github.com/ava-labs/avalanchego/api/admin" "github.com/ava-labs/avalanchego/api/auth" @@ -935,7 +935,7 @@ func (n *Node) initVMs() error { CreateAssetTxFee: n.Config.CreateAssetTxFee, }, }), - // vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), + vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), n.VMManager.RegisterFactory(context.TODO(), secp256k1fx.ID, &secp256k1fx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), nftfx.ID, &nftfx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), propertyfx.ID, &propertyfx.Factory{}), diff --git a/snow/engine/snowman/transitive.go b/snow/engine/snowman/transitive.go index cfa204123790..b9750fd6eddb 100644 --- a/snow/engine/snowman/transitive.go +++ b/snow/engine/snowman/transitive.go @@ -1011,11 +1011,11 @@ func (t *Transitive) startBlockBackfilling(ctx context.Context) error { } switch wantedBlk, err := ssVM.BackfillBlocksEnabled(ctx); { - case err != nil: - return fmt.Errorf("failed checking if state sync block backfilling is enabled: %w", err) - case wantedBlk == ids.Empty: + case err == block.ErrBlockBackfillingNotEnabled: t.Ctx.Log.Info("block backfilling not enabled") return nil + case err != nil: + return fmt.Errorf("failed checking if state sync block backfilling is enabled: %w", err) default: return t.fetch(ctx, wantedBlk) } @@ -1064,17 +1064,20 @@ func (t *Transitive) Ancestors(ctx context.Context, nodeID ids.NodeID, requestID return nil // nothing to do } - nextWantedBlkID, err := ssVM.BackfillBlocks(ctx, blks) - if err != nil { // the provided blocks couldn't be parsed + switch nextWantedBlkID, err := ssVM.BackfillBlocks(ctx, blks); { + case err == block.ErrStopBlockBackfilling: + t.Ctx.Log.Info("block backfilling done") + return nil + case err != nil: t.Ctx.Log.Debug("failed to parse blocks in Ancestors", zap.Stringer("nodeID", nodeID), zap.Uint32("requestID", requestID), zap.Error(err), ) return t.fetch(ctx, wantedBlkID) + default: + return t.fetch(ctx, nextWantedBlkID) } - - return t.fetch(ctx, nextWantedBlkID) } func (t *Transitive) GetAncestorsFailed(ctx context.Context, nodeID ids.NodeID, requestID uint32) error { diff --git a/tests/e2e/c/dynamic_fees.go b/tests/e2e/c/dynamic_fees.go index 4234c170af6f..f3a1daaf3d2c 100644 --- a/tests/e2e/c/dynamic_fees.go +++ b/tests/e2e/c/dynamic_fees.go @@ -3,167 +3,167 @@ package c -// import ( -// "math/big" -// "strings" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/stretchr/testify/require" - -// "github.com/ethereum/go-ethereum/accounts/abi" -// "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/coreth/core/types" -// "github.com/ava-labs/coreth/params" -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/tests" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/tests/fixture/testnet" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// ) - -// // This test uses the compiled bin for `hashing.sol` as -// // well as its ABI contained in `hashing_contract.go`. - -// var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { -// require := require.New(ginkgo.GinkgoT()) - -// // Need a gas limit much larger than the standard 21_000 to enable -// // the contract to induce a gas price increase -// const largeGasLimit = uint64(8_000_000) - -// // TODO(marun) What is the significance of this value? -// gasTip := big.NewInt(1000 * params.GWei) - -// ginkgo.It("should ensure that the gas price is affected by load", func() { -// ginkgo.By("creating a new private network to ensure isolation from other tests") -// privateNetwork := e2e.Env.NewPrivateNetwork() - -// ginkgo.By("allocating a pre-funded key") -// key := privateNetwork.GetConfig().FundedKeys[0] -// ethAddress := evm.GetEthAddress(key) - -// ginkgo.By("initializing a coreth client") -// node := privateNetwork.GetNodes()[0] -// nodeURI := testnet.NodeURI{ -// NodeID: node.GetID(), -// URI: node.GetProcessContext().URI, -// } -// ethClient := e2e.Env.NewEthClient(nodeURI) - -// ginkgo.By("initializing a transaction signer") -// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) -// require.NoError(err) -// signer := types.NewEIP155Signer(cChainID) -// ecdsaKey := key.ToECDSA() -// sign := func(tx *types.Transaction) *types.Transaction { -// signedTx, err := types.SignTx(tx, signer, ecdsaKey) -// require.NoError(err) -// return signedTx -// } - -// var contractAddress common.Address -// ginkgo.By("deploying an expensive contract", func() { -// // Create transaction -// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) -// require.NoError(err) -// compiledContract := common.Hex2Bytes(hashingCompiledContract) -// tx := types.NewTx(&types.LegacyTx{ -// Nonce: nonce, -// GasPrice: gasTip, -// Gas: largeGasLimit, -// Value: common.Big0, -// Data: compiledContract, -// }) - -// // Send the transaction and wait for acceptance -// signedTx := sign(tx) -// receipt := e2e.SendEthTransaction(ethClient, signedTx) - -// contractAddress = receipt.ContractAddress -// }) - -// var gasPrice *big.Int -// ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { -// // Evaluate the bytes representation of the contract -// hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) -// require.NoError(err) -// contractData, err := hashingABI.Pack("hashIt") -// require.NoError(err) - -// var initialGasPrice *big.Int -// e2e.Eventually(func() bool { -// // Check the gas price -// var err error -// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) -// require.NoError(err) -// if initialGasPrice == nil { -// initialGasPrice = gasPrice -// tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) -// } else if gasPrice.Cmp(initialGasPrice) > 0 { -// // Gas price has increased -// tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) -// return true -// } - -// // Create the transaction -// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) -// require.NoError(err) -// tx := types.NewTx(&types.LegacyTx{ -// Nonce: nonce, -// GasPrice: gasTip, -// Gas: largeGasLimit, -// To: &contractAddress, -// Value: common.Big0, -// Data: contractData, -// }) - -// // Send the transaction and wait for acceptance -// signedTx := sign(tx) -// _ = e2e.SendEthTransaction(ethClient, signedTx) - -// // The gas price will be checked at the start of the next iteration -// return false -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") -// }) - -// ginkgo.By("waiting for the gas price to decrease...", func() { -// initialGasPrice := gasPrice -// e2e.Eventually(func() bool { -// var err error -// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) -// require.NoError(err) -// tests.Outf("{{blue}}.{{/}}") -// return initialGasPrice.Cmp(gasPrice) > 0 -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") -// tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) -// }) - -// ginkgo.By("sending funds at the current gas price", func() { -// // Create a recipient address -// factory := secp256k1.Factory{} -// recipientKey, err := factory.NewPrivateKey() -// require.NoError(err) -// recipientEthAddress := evm.GetEthAddress(recipientKey) - -// // Create transaction -// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) -// require.NoError(err) -// tx := types.NewTx(&types.LegacyTx{ -// Nonce: nonce, -// GasPrice: gasPrice, -// Gas: e2e.DefaultGasLimit, -// To: &recipientEthAddress, -// Value: common.Big0, -// }) - -// // Send the transaction and wait for acceptance -// signedTx := sign(tx) -// _ = e2e.SendEthTransaction(ethClient, signedTx) -// }) - -// e2e.CheckBootstrapIsPossible(privateNetwork) -// }) -// }) +import ( + "math/big" + "strings" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/coreth/params" + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/tests" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/tests/fixture/testnet" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +) + +// This test uses the compiled bin for `hashing.sol` as +// well as its ABI contained in `hashing_contract.go`. + +var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { + require := require.New(ginkgo.GinkgoT()) + + // Need a gas limit much larger than the standard 21_000 to enable + // the contract to induce a gas price increase + const largeGasLimit = uint64(8_000_000) + + // TODO(marun) What is the significance of this value? + gasTip := big.NewInt(1000 * params.GWei) + + ginkgo.It("should ensure that the gas price is affected by load", func() { + ginkgo.By("creating a new private network to ensure isolation from other tests") + privateNetwork := e2e.Env.NewPrivateNetwork() + + ginkgo.By("allocating a pre-funded key") + key := privateNetwork.GetConfig().FundedKeys[0] + ethAddress := evm.GetEthAddress(key) + + ginkgo.By("initializing a coreth client") + node := privateNetwork.GetNodes()[0] + nodeURI := testnet.NodeURI{ + NodeID: node.GetID(), + URI: node.GetProcessContext().URI, + } + ethClient := e2e.Env.NewEthClient(nodeURI) + + ginkgo.By("initializing a transaction signer") + cChainID, err := ethClient.ChainID(e2e.DefaultContext()) + require.NoError(err) + signer := types.NewEIP155Signer(cChainID) + ecdsaKey := key.ToECDSA() + sign := func(tx *types.Transaction) *types.Transaction { + signedTx, err := types.SignTx(tx, signer, ecdsaKey) + require.NoError(err) + return signedTx + } + + var contractAddress common.Address + ginkgo.By("deploying an expensive contract", func() { + // Create transaction + nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) + require.NoError(err) + compiledContract := common.Hex2Bytes(hashingCompiledContract) + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + GasPrice: gasTip, + Gas: largeGasLimit, + Value: common.Big0, + Data: compiledContract, + }) + + // Send the transaction and wait for acceptance + signedTx := sign(tx) + receipt := e2e.SendEthTransaction(ethClient, signedTx) + + contractAddress = receipt.ContractAddress + }) + + var gasPrice *big.Int + ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { + // Evaluate the bytes representation of the contract + hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) + require.NoError(err) + contractData, err := hashingABI.Pack("hashIt") + require.NoError(err) + + var initialGasPrice *big.Int + e2e.Eventually(func() bool { + // Check the gas price + var err error + gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) + require.NoError(err) + if initialGasPrice == nil { + initialGasPrice = gasPrice + tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) + } else if gasPrice.Cmp(initialGasPrice) > 0 { + // Gas price has increased + tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) + return true + } + + // Create the transaction + nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) + require.NoError(err) + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + GasPrice: gasTip, + Gas: largeGasLimit, + To: &contractAddress, + Value: common.Big0, + Data: contractData, + }) + + // Send the transaction and wait for acceptance + signedTx := sign(tx) + _ = e2e.SendEthTransaction(ethClient, signedTx) + + // The gas price will be checked at the start of the next iteration + return false + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") + }) + + ginkgo.By("waiting for the gas price to decrease...", func() { + initialGasPrice := gasPrice + e2e.Eventually(func() bool { + var err error + gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) + require.NoError(err) + tests.Outf("{{blue}}.{{/}}") + return initialGasPrice.Cmp(gasPrice) > 0 + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") + tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) + }) + + ginkgo.By("sending funds at the current gas price", func() { + // Create a recipient address + factory := secp256k1.Factory{} + recipientKey, err := factory.NewPrivateKey() + require.NoError(err) + recipientEthAddress := evm.GetEthAddress(recipientKey) + + // Create transaction + nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) + require.NoError(err) + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + GasPrice: gasPrice, + Gas: e2e.DefaultGasLimit, + To: &recipientEthAddress, + Value: common.Big0, + }) + + // Send the transaction and wait for acceptance + signedTx := sign(tx) + _ = e2e.SendEthTransaction(ethClient, signedTx) + }) + + e2e.CheckBootstrapIsPossible(privateNetwork) + }) +}) diff --git a/tests/e2e/c/interchain_workflow.go b/tests/e2e/c/interchain_workflow.go index a072596e1dc9..47c430d4c12a 100644 --- a/tests/e2e/c/interchain_workflow.go +++ b/tests/e2e/c/interchain_workflow.go @@ -3,164 +3,164 @@ package c -// import ( -// "math/big" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/stretchr/testify/require" - -// "github.com/ava-labs/coreth/core/types" -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { -// require := require.New(ginkgo.GinkgoT()) - -// const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer - -// ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { -// ginkgo.By("initializing a new eth client") -// // Select a random node URI to use for both the eth client and -// // the wallet to avoid having to verify that all nodes are at -// // the same height before initializing the wallet. -// nodeURI := e2e.Env.GetRandomNodeURI() -// ethClient := e2e.Env.NewEthClient(nodeURI) - -// ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") -// senderKey := e2e.Env.AllocateFundedKey() -// senderEthAddress := evm.GetEthAddress(senderKey) -// factory := secp256k1.Factory{} -// recipientKey, err := factory.NewPrivateKey() -// require.NoError(err) -// recipientEthAddress := evm.GetEthAddress(recipientKey) - -// ginkgo.By("sending funds from one address to another on the C-Chain", func() { -// // Create transaction -// acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) -// require.NoError(err) -// gasPrice := e2e.SuggestGasPrice(ethClient) -// tx := types.NewTransaction( -// acceptedNonce, -// recipientEthAddress, -// big.NewInt(int64(txAmount)), -// e2e.DefaultGasLimit, -// gasPrice, -// nil, -// ) - -// // Sign transaction -// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) -// require.NoError(err) -// signer := types.NewEIP155Signer(cChainID) -// signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) -// require.NoError(err) - -// _ = e2e.SendEthTransaction(ethClient, signedTx) - -// ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") -// e2e.Eventually(func() bool { -// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) -// require.NoError(err) -// return balance.Cmp(big.NewInt(0)) > 0 -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") -// }) - -// // Wallet must be initialized after sending funds on the -// // C-Chain with the same node URI to ensure wallet state -// // matches on-chain state. -// ginkgo.By("initializing a keychain and associated wallet") -// keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) -// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) -// xWallet := baseWallet.X() -// cWallet := baseWallet.C() -// pWallet := baseWallet.P() - -// ginkgo.By("defining common configuration") -// avaxAssetID := xWallet.AVAXAssetID() -// // Use the same owner for import funds to X-Chain and P-Chain -// recipientOwner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// recipientKey.Address(), -// }, -// } -// // Use the same outputs for both X-Chain and P-Chain exports -// exportOutputs := []*secp256k1fx.TransferOutput{ -// { -// Amt: txAmount, -// OutputOwners: secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// keychain.Keys[0].Address(), -// }, -// }, -// }, -// } - -// ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { -// _, err := cWallet.IssueExportTx( -// xWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { -// _, err := xWallet.IssueImportTx( -// cWallet.BlockchainID(), -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { -// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { -// _, err := cWallet.IssueExportTx( -// constants.PlatformChainID, -// exportOutputs, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { -// _, err = pWallet.IssueImportTx( -// cWallet.BlockchainID(), -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { -// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) -// }) -// }) +import ( + "math/big" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { + require := require.New(ginkgo.GinkgoT()) + + const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer + + ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { + ginkgo.By("initializing a new eth client") + // Select a random node URI to use for both the eth client and + // the wallet to avoid having to verify that all nodes are at + // the same height before initializing the wallet. + nodeURI := e2e.Env.GetRandomNodeURI() + ethClient := e2e.Env.NewEthClient(nodeURI) + + ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") + senderKey := e2e.Env.AllocateFundedKey() + senderEthAddress := evm.GetEthAddress(senderKey) + factory := secp256k1.Factory{} + recipientKey, err := factory.NewPrivateKey() + require.NoError(err) + recipientEthAddress := evm.GetEthAddress(recipientKey) + + ginkgo.By("sending funds from one address to another on the C-Chain", func() { + // Create transaction + acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) + require.NoError(err) + gasPrice := e2e.SuggestGasPrice(ethClient) + tx := types.NewTransaction( + acceptedNonce, + recipientEthAddress, + big.NewInt(int64(txAmount)), + e2e.DefaultGasLimit, + gasPrice, + nil, + ) + + // Sign transaction + cChainID, err := ethClient.ChainID(e2e.DefaultContext()) + require.NoError(err) + signer := types.NewEIP155Signer(cChainID) + signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) + require.NoError(err) + + _ = e2e.SendEthTransaction(ethClient, signedTx) + + ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") + e2e.Eventually(func() bool { + balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) + require.NoError(err) + return balance.Cmp(big.NewInt(0)) > 0 + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") + }) + + // Wallet must be initialized after sending funds on the + // C-Chain with the same node URI to ensure wallet state + // matches on-chain state. + ginkgo.By("initializing a keychain and associated wallet") + keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) + baseWallet := e2e.Env.NewWallet(keychain, nodeURI) + xWallet := baseWallet.X() + cWallet := baseWallet.C() + pWallet := baseWallet.P() + + ginkgo.By("defining common configuration") + avaxAssetID := xWallet.AVAXAssetID() + // Use the same owner for import funds to X-Chain and P-Chain + recipientOwner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + recipientKey.Address(), + }, + } + // Use the same outputs for both X-Chain and P-Chain exports + exportOutputs := []*secp256k1fx.TransferOutput{ + { + Amt: txAmount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + keychain.Keys[0].Address(), + }, + }, + }, + } + + ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { + _, err := cWallet.IssueExportTx( + xWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { + _, err := xWallet.IssueImportTx( + cWallet.BlockchainID(), + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { + balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { + _, err := cWallet.IssueExportTx( + constants.PlatformChainID, + exportOutputs, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { + _, err = pWallet.IssueImportTx( + cWallet.BlockchainID(), + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { + balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) + }) +}) diff --git a/tests/e2e/e2e.go b/tests/e2e/e2e.go index 790748b705b1..130f33f1197c 100644 --- a/tests/e2e/e2e.go +++ b/tests/e2e/e2e.go @@ -7,24 +7,22 @@ package e2e import ( "context" "encoding/json" - - // "errors" - // "fmt" - // "math/big" + "errors" + "fmt" + "math/big" "math/rand" "os" "path/filepath" - - // "strings" + "strings" "time" ginkgo "github.com/onsi/ginkgo/v2" "github.com/stretchr/testify/require" - // "github.com/ava-labs/coreth/core/types" - // "github.com/ava-labs/coreth/ethclient" - // "github.com/ava-labs/coreth/interfaces" + "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/coreth/ethclient" + "github.com/ava-labs/coreth/interfaces" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/tests" @@ -136,7 +134,7 @@ func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain, nodeURI tes baseWallet, err := primary.MakeWallet(DefaultContext(), &primary.WalletConfig{ URI: nodeURI.URI, AVAXKeychain: keychain, - // EthKeychain: keychain, + EthKeychain: keychain, }) te.require.NoError(err) return primary.NewWalletWithOptions( @@ -149,16 +147,16 @@ func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain, nodeURI tes ) } -// // Create a new eth client targeting the specified node URI. -// // TODO(marun) Make this a regular function. -// func (te *TestEnvironment) NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { -// tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) -// nodeAddress := strings.Split(nodeURI.URI, "//")[1] -// uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) -// client, err := ethclient.Dial(uri) -// te.require.NoError(err) -// return client -// } +// Create a new eth client targeting the specified node URI. +// TODO(marun) Make this a regular function. +func (te *TestEnvironment) NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { + tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) + nodeAddress := strings.Split(nodeURI.URI, "//")[1] + uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) + client, err := ethclient.Dial(uri) + te.require.NoError(err) + return client +} // Create a new private network that is not shared with other tests. func (te *TestEnvironment) NewPrivateNetwork() testnet.Network { @@ -233,49 +231,49 @@ func WaitForHealthy(node testnet.Node) { require.NoError(ginkgo.GinkgoT(), testnet.WaitForHealthy(DefaultContext(), node)) } -// // Sends an eth transaction, waits for the transaction receipt to be issued -// // and checks that the receipt indicates success. -// func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { -// require := require.New(ginkgo.GinkgoT()) - -// txID := signedTx.Hash() -// tests.Outf(" sending eth transaction with ID: %s\n", txID) - -// require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) - -// // Wait for the receipt -// var receipt *types.Receipt -// Eventually(func() bool { -// var err error -// receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) -// if errors.Is(err, interfaces.NotFound) { -// return false // Transaction is still pending -// } -// require.NoError(err) -// return true -// }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") - -// require.Equal(receipt.Status, types.ReceiptStatusSuccessful) -// return receipt -// } - -// // Determines the suggested gas price for the configured client that will -// // maximize the chances of transaction acceptance. -// func SuggestGasPrice(ethClient ethclient.Client) *big.Int { -// gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) -// require.NoError(ginkgo.GinkgoT(), err) -// // Double the suggested gas price to maximize the chances of -// // acceptance. Maybe this can be revisited pending resolution of -// // https://github.com/ava-labs/coreth/issues/314. -// gasPrice.Add(gasPrice, gasPrice) -// return gasPrice -// } - -// // Helper simplifying use via an option of a gas price appropriate for testing. -// func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { -// baseFee := SuggestGasPrice(ethClient) -// return common.WithBaseFee(baseFee) -// } +// Sends an eth transaction, waits for the transaction receipt to be issued +// and checks that the receipt indicates success. +func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { + require := require.New(ginkgo.GinkgoT()) + + txID := signedTx.Hash() + tests.Outf(" sending eth transaction with ID: %s\n", txID) + + require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) + + // Wait for the receipt + var receipt *types.Receipt + Eventually(func() bool { + var err error + receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) + if errors.Is(err, interfaces.NotFound) { + return false // Transaction is still pending + } + require.NoError(err) + return true + }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") + + require.Equal(receipt.Status, types.ReceiptStatusSuccessful) + return receipt +} + +// Determines the suggested gas price for the configured client that will +// maximize the chances of transaction acceptance. +func SuggestGasPrice(ethClient ethclient.Client) *big.Int { + gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) + require.NoError(ginkgo.GinkgoT(), err) + // Double the suggested gas price to maximize the chances of + // acceptance. Maybe this can be revisited pending resolution of + // https://github.com/ava-labs/coreth/issues/314. + gasPrice.Add(gasPrice, gasPrice) + return gasPrice +} + +// Helper simplifying use via an option of a gas price appropriate for testing. +func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { + baseFee := SuggestGasPrice(ethClient) + return common.WithBaseFee(baseFee) +} // Verify that a new node can bootstrap into the network. func CheckBootstrapIsPossible(network testnet.Network) { diff --git a/tests/e2e/p/interchain_workflow.go b/tests/e2e/p/interchain_workflow.go index c5bc47517967..10c15fd002a7 100644 --- a/tests/e2e/p/interchain_workflow.go +++ b/tests/e2e/p/interchain_workflow.go @@ -3,226 +3,226 @@ package p -// import ( -// "math/big" -// "time" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/spf13/cast" - -// "github.com/stretchr/testify/require" - -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/api/info" -// "github.com/ava-labs/avalanchego/config" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/tests/fixture/testnet" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/platformvm/reward" -// "github.com/ava-labs/avalanchego/vms/platformvm/txs" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { -// require := require.New(ginkgo.GinkgoT()) - -// const ( -// transferAmount = 10 * units.Avax -// weight = 2_000 * units.Avax // Used for both validation and delegation -// ) - -// ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { -// network := e2e.Env.GetNetwork() - -// ginkgo.By("checking that the network has a compatible minimum stake duration", func() { -// minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) -// require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) -// }) - -// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") -// factory := secp256k1.Factory{} -// recipientKey, err := factory.NewPrivateKey() -// require.NoError(err) -// keychain := e2e.Env.NewKeychain(1) -// keychain.Add(recipientKey) -// nodeURI := e2e.Env.GetRandomNodeURI() -// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) -// xWallet := baseWallet.X() -// cWallet := baseWallet.C() -// pWallet := baseWallet.P() - -// ginkgo.By("defining common configuration") -// recipientEthAddress := evm.GetEthAddress(recipientKey) -// avaxAssetID := xWallet.AVAXAssetID() -// // Use the same owner for sending to X-Chain and importing funds to P-Chain -// recipientOwner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// recipientKey.Address(), -// }, -// } -// // Use the same outputs for both X-Chain and C-Chain exports -// exportOutputs := []*avax.TransferableOutput{ -// { -// Asset: avax.Asset{ -// ID: avaxAssetID, -// }, -// Out: &secp256k1fx.TransferOutput{ -// Amt: transferAmount, -// OutputOwners: secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// keychain.Keys[0].Address(), -// }, -// }, -// }, -// }, -// } - -// ginkgo.By("adding new node and waiting for it to report healthy") -// node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) -// e2e.WaitForHealthy(node) - -// ginkgo.By("retrieving new node's id and pop") -// infoClient := info.NewClient(node.GetProcessContext().URI) -// nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) -// require.NoError(err) - -// ginkgo.By("adding the new node as a validator", func() { -// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) -// // Validation duration doesn't actually matter to this -// // test - it is only ensuring that adding a validator -// // doesn't break interchain transfer. -// endTime := startTime.Add(30 * time.Second) - -// rewardKey, err := factory.NewPrivateKey() -// require.NoError(err) - -// const ( -// delegationPercent = 0.10 // 10% -// delegationShare = reward.PercentDenominator * delegationPercent -// ) - -// _, err = pWallet.IssueAddPermissionlessValidatorTx( -// &txs.SubnetValidator{ -// Validator: txs.Validator{ -// NodeID: nodeID, -// Start: uint64(startTime.Unix()), -// End: uint64(endTime.Unix()), -// Wght: weight, -// }, -// Subnet: constants.PrimaryNetworkID, -// }, -// nodePOP, -// pWallet.AVAXAssetID(), -// &secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{rewardKey.Address()}, -// }, -// &secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{rewardKey.Address()}, -// }, -// delegationShare, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("adding a delegator to the new node", func() { -// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) -// // Delegation duration doesn't actually matter to this -// // test - it is only ensuring that adding a delegator -// // doesn't break interchain transfer. -// endTime := startTime.Add(15 * time.Second) - -// rewardKey, err := factory.NewPrivateKey() -// require.NoError(err) - -// _, err = pWallet.IssueAddPermissionlessDelegatorTx( -// &txs.SubnetValidator{ -// Validator: txs.Validator{ -// NodeID: nodeID, -// Start: uint64(startTime.Unix()), -// End: uint64(endTime.Unix()), -// Wght: weight, -// }, -// Subnet: constants.PrimaryNetworkID, -// }, -// pWallet.AVAXAssetID(), -// &secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{rewardKey.Address()}, -// }, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { -// _, err := pWallet.IssueExportTx( -// xWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { -// _, err := xWallet.IssueImportTx( -// constants.PlatformChainID, -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { -// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { -// _, err := pWallet.IssueExportTx( -// cWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("initializing a new eth client") -// ethClient := e2e.Env.NewEthClient(nodeURI) - -// ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { -// _, err := cWallet.IssueImportTx( -// constants.PlatformChainID, -// recipientEthAddress, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") -// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) -// require.NoError(err) -// require.Positive(balance.Cmp(big.NewInt(0))) - -// ginkgo.By("stopping validator node to free up resources for a bootstrap check") -// require.NoError(node.Stop()) - -// e2e.CheckBootstrapIsPossible(network) -// }) -// }) +import ( + "math/big" + "time" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/spf13/cast" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/api/info" + "github.com/ava-labs/avalanchego/config" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/tests/fixture/testnet" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/platformvm/reward" + "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { + require := require.New(ginkgo.GinkgoT()) + + const ( + transferAmount = 10 * units.Avax + weight = 2_000 * units.Avax // Used for both validation and delegation + ) + + ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { + network := e2e.Env.GetNetwork() + + ginkgo.By("checking that the network has a compatible minimum stake duration", func() { + minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) + require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) + }) + + ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") + factory := secp256k1.Factory{} + recipientKey, err := factory.NewPrivateKey() + require.NoError(err) + keychain := e2e.Env.NewKeychain(1) + keychain.Add(recipientKey) + nodeURI := e2e.Env.GetRandomNodeURI() + baseWallet := e2e.Env.NewWallet(keychain, nodeURI) + xWallet := baseWallet.X() + cWallet := baseWallet.C() + pWallet := baseWallet.P() + + ginkgo.By("defining common configuration") + recipientEthAddress := evm.GetEthAddress(recipientKey) + avaxAssetID := xWallet.AVAXAssetID() + // Use the same owner for sending to X-Chain and importing funds to P-Chain + recipientOwner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + recipientKey.Address(), + }, + } + // Use the same outputs for both X-Chain and C-Chain exports + exportOutputs := []*avax.TransferableOutput{ + { + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: transferAmount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + keychain.Keys[0].Address(), + }, + }, + }, + }, + } + + ginkgo.By("adding new node and waiting for it to report healthy") + node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) + e2e.WaitForHealthy(node) + + ginkgo.By("retrieving new node's id and pop") + infoClient := info.NewClient(node.GetProcessContext().URI) + nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) + require.NoError(err) + + ginkgo.By("adding the new node as a validator", func() { + startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) + // Validation duration doesn't actually matter to this + // test - it is only ensuring that adding a validator + // doesn't break interchain transfer. + endTime := startTime.Add(30 * time.Second) + + rewardKey, err := factory.NewPrivateKey() + require.NoError(err) + + const ( + delegationPercent = 0.10 // 10% + delegationShare = reward.PercentDenominator * delegationPercent + ) + + _, err = pWallet.IssueAddPermissionlessValidatorTx( + &txs.SubnetValidator{ + Validator: txs.Validator{ + NodeID: nodeID, + Start: uint64(startTime.Unix()), + End: uint64(endTime.Unix()), + Wght: weight, + }, + Subnet: constants.PrimaryNetworkID, + }, + nodePOP, + pWallet.AVAXAssetID(), + &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{rewardKey.Address()}, + }, + &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{rewardKey.Address()}, + }, + delegationShare, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("adding a delegator to the new node", func() { + startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) + // Delegation duration doesn't actually matter to this + // test - it is only ensuring that adding a delegator + // doesn't break interchain transfer. + endTime := startTime.Add(15 * time.Second) + + rewardKey, err := factory.NewPrivateKey() + require.NoError(err) + + _, err = pWallet.IssueAddPermissionlessDelegatorTx( + &txs.SubnetValidator{ + Validator: txs.Validator{ + NodeID: nodeID, + Start: uint64(startTime.Unix()), + End: uint64(endTime.Unix()), + Wght: weight, + }, + Subnet: constants.PrimaryNetworkID, + }, + pWallet.AVAXAssetID(), + &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{rewardKey.Address()}, + }, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { + _, err := pWallet.IssueExportTx( + xWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { + _, err := xWallet.IssueImportTx( + constants.PlatformChainID, + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { + balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { + _, err := pWallet.IssueExportTx( + cWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("initializing a new eth client") + ethClient := e2e.Env.NewEthClient(nodeURI) + + ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { + _, err := cWallet.IssueImportTx( + constants.PlatformChainID, + recipientEthAddress, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") + balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) + require.NoError(err) + require.Positive(balance.Cmp(big.NewInt(0))) + + ginkgo.By("stopping validator node to free up resources for a bootstrap check") + require.NoError(node.Stop()) + + e2e.CheckBootstrapIsPossible(network) + }) +}) diff --git a/tests/e2e/x/interchain_workflow.go b/tests/e2e/x/interchain_workflow.go index 5443e1a54ad4..550689ff60c9 100644 --- a/tests/e2e/x/interchain_workflow.go +++ b/tests/e2e/x/interchain_workflow.go @@ -3,152 +3,152 @@ package x -// import ( -// "math/big" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/stretchr/testify/require" - -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { -// require := require.New(ginkgo.GinkgoT()) - -// const transferAmount = 10 * units.Avax - -// ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { -// nodeURI := e2e.Env.GetRandomNodeURI() - -// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") -// factory := secp256k1.Factory{} -// recipientKey, err := factory.NewPrivateKey() -// require.NoError(err) -// keychain := e2e.Env.NewKeychain(1) -// keychain.Add(recipientKey) -// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) -// xWallet := baseWallet.X() -// cWallet := baseWallet.C() -// pWallet := baseWallet.P() - -// ginkgo.By("defining common configuration") -// recipientEthAddress := evm.GetEthAddress(recipientKey) -// avaxAssetID := xWallet.AVAXAssetID() -// // Use the same owner for sending to X-Chain and importing funds to P-Chain -// recipientOwner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// recipientKey.Address(), -// }, -// } -// // Use the same outputs for both C-Chain and P-Chain exports -// exportOutputs := []*avax.TransferableOutput{ -// { -// Asset: avax.Asset{ -// ID: avaxAssetID, -// }, -// Out: &secp256k1fx.TransferOutput{ -// Amt: transferAmount, -// OutputOwners: secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// keychain.Keys[0].Address(), -// }, -// }, -// }, -// }, -// } - -// ginkgo.By("sending funds from one address to another on the X-Chain", func() { -// _, err = xWallet.IssueBaseTx( -// []*avax.TransferableOutput{{ -// Asset: avax.Asset{ -// ID: avaxAssetID, -// }, -// Out: &secp256k1fx.TransferOutput{ -// Amt: transferAmount, -// OutputOwners: recipientOwner, -// }, -// }}, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { -// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { -// _, err := xWallet.IssueExportTx( -// cWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("initializing a new eth client") -// ethClient := e2e.Env.NewEthClient(nodeURI) - -// ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { -// _, err := cWallet.IssueImportTx( -// xWallet.BlockchainID(), -// recipientEthAddress, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") -// e2e.Eventually(func() bool { -// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) -// require.NoError(err) -// return balance.Cmp(big.NewInt(0)) > 0 -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") - -// ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { -// _, err := xWallet.IssueExportTx( -// constants.PlatformChainID, -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { -// _, err := pWallet.IssueImportTx( -// xWallet.BlockchainID(), -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { -// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) -// }) -// }) +import ( + "math/big" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { + require := require.New(ginkgo.GinkgoT()) + + const transferAmount = 10 * units.Avax + + ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { + nodeURI := e2e.Env.GetRandomNodeURI() + + ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") + factory := secp256k1.Factory{} + recipientKey, err := factory.NewPrivateKey() + require.NoError(err) + keychain := e2e.Env.NewKeychain(1) + keychain.Add(recipientKey) + baseWallet := e2e.Env.NewWallet(keychain, nodeURI) + xWallet := baseWallet.X() + cWallet := baseWallet.C() + pWallet := baseWallet.P() + + ginkgo.By("defining common configuration") + recipientEthAddress := evm.GetEthAddress(recipientKey) + avaxAssetID := xWallet.AVAXAssetID() + // Use the same owner for sending to X-Chain and importing funds to P-Chain + recipientOwner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + recipientKey.Address(), + }, + } + // Use the same outputs for both C-Chain and P-Chain exports + exportOutputs := []*avax.TransferableOutput{ + { + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: transferAmount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + keychain.Keys[0].Address(), + }, + }, + }, + }, + } + + ginkgo.By("sending funds from one address to another on the X-Chain", func() { + _, err = xWallet.IssueBaseTx( + []*avax.TransferableOutput{{ + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: transferAmount, + OutputOwners: recipientOwner, + }, + }}, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { + balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { + _, err := xWallet.IssueExportTx( + cWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("initializing a new eth client") + ethClient := e2e.Env.NewEthClient(nodeURI) + + ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { + _, err := cWallet.IssueImportTx( + xWallet.BlockchainID(), + recipientEthAddress, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") + e2e.Eventually(func() bool { + balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) + require.NoError(err) + return balance.Cmp(big.NewInt(0)) > 0 + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") + + ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { + _, err := xWallet.IssueExportTx( + constants.PlatformChainID, + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { + _, err := pWallet.IssueImportTx( + xWallet.BlockchainID(), + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { + balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) + }) +}) diff --git a/tests/fixture/testnet/config.go b/tests/fixture/testnet/config.go index 73537ea74744..10d51104eef4 100644 --- a/tests/fixture/testnet/config.go +++ b/tests/fixture/testnet/config.go @@ -15,9 +15,9 @@ import ( "github.com/spf13/cast" - // "github.com/ava-labs/coreth/core" - // "github.com/ava-labs/coreth/params" - // "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/coreth/core" + "github.com/ava-labs/coreth/params" + "github.com/ava-labs/coreth/plugin/evm" "github.com/ava-labs/avalanchego/config" "github.com/ava-labs/avalanchego/genesis" @@ -143,15 +143,15 @@ func (c *NetworkConfig) EnsureGenesis(networkID uint32, validatorIDs []ids.NodeI // Ensure pre-funded keys have arbitrary large balances on both chains to support testing xChainBalances := make(XChainBalanceMap, len(c.FundedKeys)) - // cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) - // for _, key := range c.FundedKeys { - // xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount - // cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ - // Balance: DefaultFundedKeyCChainAmount, - // } - // } - - genesis, err := NewTestGenesis(networkID, xChainBalances /*, cChainBalances,*/, validatorIDs) + cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) + for _, key := range c.FundedKeys { + xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount + cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ + Balance: DefaultFundedKeyCChainAmount, + } + } + + genesis, err := NewTestGenesis(networkID, xChainBalances, cChainBalances, validatorIDs) if err != nil { return err } @@ -311,7 +311,7 @@ type XChainBalanceMap map[ids.ShortID]uint64 func NewTestGenesis( networkID uint32, xChainBalances XChainBalanceMap, - // cChainBalances core.GenesisAlloc, + cChainBalances core.GenesisAlloc, validatorIDs []ids.NodeID, ) (*genesis.UnparsedConfig, error) { // Validate inputs @@ -322,7 +322,7 @@ func NewTestGenesis( if len(validatorIDs) == 0 { return nil, errMissingValidatorsForGenesis } - if len(xChainBalances) == 0 /*|| len(cChainBalances) == 0*/ { + if len(xChainBalances) == 0 || len(cChainBalances) == 0 { return nil, errMissingBalancesForGenesis } @@ -394,20 +394,20 @@ func NewTestGenesis( ) } - // // Define C-Chain genesis - // cChainGenesis := &core.Genesis{ - // Config: ¶ms.ChainConfig{ - // ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary - // }, - // Difficulty: big.NewInt(0), // Difficulty is a mandatory field - // GasLimit: DefaultGasLimit, - // Alloc: cChainBalances, - // } - // cChainGenesisBytes, err := json.Marshal(cChainGenesis) - // if err != nil { - // return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) - // } - // config.CChainGenesis = string(cChainGenesisBytes) + // Define C-Chain genesis + cChainGenesis := &core.Genesis{ + Config: ¶ms.ChainConfig{ + ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary + }, + Difficulty: big.NewInt(0), // Difficulty is a mandatory field + GasLimit: DefaultGasLimit, + Alloc: cChainBalances, + } + cChainGenesisBytes, err := json.Marshal(cChainGenesis) + if err != nil { + return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) + } + config.CChainGenesis = string(cChainGenesisBytes) // Give staking rewards for initial validators to a random address. Any testing of staking rewards // will be easier to perform with nodes other than the initial validators since the timing of diff --git a/vms/example/xsvm/cmd/chain/create/cmd.go b/vms/example/xsvm/cmd/chain/create/cmd.go index 043b4298dcdf..1f00491a4ce6 100644 --- a/vms/example/xsvm/cmd/chain/create/cmd.go +++ b/vms/example/xsvm/cmd/chain/create/cmd.go @@ -42,9 +42,9 @@ func createFunc(c *cobra.Command, args []string) error { // that [uri] is hosting. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: config.URI, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: config.URI, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(config.SubnetID), }) if err != nil { diff --git a/wallet/chain/c/backend.go b/wallet/chain/c/backend.go index b88c8c643bc3..0a735116b646 100644 --- a/wallet/chain/c/backend.go +++ b/wallet/chain/c/backend.go @@ -3,153 +3,153 @@ package c -// import ( -// "errors" -// "fmt" -// "math/big" -// "sync" - -// stdcontext "context" - -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/database" -// "github.com/ava-labs/avalanchego/utils/math" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var ( -// _ Backend = (*backend)(nil) - -// errUnknownTxType = errors.New("unknown tx type") -// ) - -// // Backend defines the full interface required to support a C-chain wallet. -// type Backend interface { -// common.ChainUTXOs -// BuilderBackend -// SignerBackend - -// AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error -// } - -// type backend struct { -// Context -// common.ChainUTXOs - -// accountsLock sync.RWMutex -// accounts map[ethcommon.Address]*Account -// } - -// type Account struct { -// Balance *big.Int -// Nonce uint64 -// } - -// func NewBackend( -// ctx Context, -// utxos common.ChainUTXOs, -// accounts map[ethcommon.Address]*Account, -// ) Backend { -// return &backend{ -// Context: ctx, -// ChainUTXOs: utxos, -// accounts: accounts, -// } -// } - -// func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { -// switch tx := tx.UnsignedAtomicTx.(type) { -// case *evm.UnsignedImportTx: -// for _, input := range tx.ImportedInputs { -// utxoID := input.InputID() -// if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { -// return err -// } -// } - -// b.accountsLock.Lock() -// defer b.accountsLock.Unlock() - -// for _, output := range tx.Outs { -// account, ok := b.accounts[output.Address] -// if !ok { -// continue -// } - -// balance := new(big.Int).SetUint64(output.Amount) -// balance.Mul(balance, avaxConversionRate) -// account.Balance.Add(account.Balance, balance) -// } -// case *evm.UnsignedExportTx: -// txID := tx.ID() -// for i, out := range tx.ExportedOutputs { -// err := b.AddUTXO( -// ctx, -// tx.DestinationChain, -// &avax.UTXO{ -// UTXOID: avax.UTXOID{ -// TxID: txID, -// OutputIndex: uint32(i), -// }, -// Asset: avax.Asset{ID: out.AssetID()}, -// Out: out.Out, -// }, -// ) -// if err != nil { -// return err -// } -// } - -// b.accountsLock.Lock() -// defer b.accountsLock.Unlock() - -// for _, input := range tx.Ins { -// account, ok := b.accounts[input.Address] -// if !ok { -// continue -// } - -// balance := new(big.Int).SetUint64(input.Amount) -// balance.Mul(balance, avaxConversionRate) -// if account.Balance.Cmp(balance) == -1 { -// return errInsufficientFunds -// } -// account.Balance.Sub(account.Balance, balance) - -// newNonce, err := math.Add64(input.Nonce, 1) -// if err != nil { -// return err -// } -// account.Nonce = newNonce -// } -// default: -// return fmt.Errorf("%w: %T", errUnknownTxType, tx) -// } -// return nil -// } - -// func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { -// b.accountsLock.RLock() -// defer b.accountsLock.RUnlock() - -// account, exists := b.accounts[addr] -// if !exists { -// return nil, database.ErrNotFound -// } -// return account.Balance, nil -// } - -// func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { -// b.accountsLock.RLock() -// defer b.accountsLock.RUnlock() - -// account, exists := b.accounts[addr] -// if !exists { -// return 0, database.ErrNotFound -// } -// return account.Nonce, nil -// } +import ( + "errors" + "fmt" + "math/big" + "sync" + + stdcontext "context" + + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/utils/math" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var ( + _ Backend = (*backend)(nil) + + errUnknownTxType = errors.New("unknown tx type") +) + +// Backend defines the full interface required to support a C-chain wallet. +type Backend interface { + common.ChainUTXOs + BuilderBackend + SignerBackend + + AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error +} + +type backend struct { + Context + common.ChainUTXOs + + accountsLock sync.RWMutex + accounts map[ethcommon.Address]*Account +} + +type Account struct { + Balance *big.Int + Nonce uint64 +} + +func NewBackend( + ctx Context, + utxos common.ChainUTXOs, + accounts map[ethcommon.Address]*Account, +) Backend { + return &backend{ + Context: ctx, + ChainUTXOs: utxos, + accounts: accounts, + } +} + +func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { + switch tx := tx.UnsignedAtomicTx.(type) { + case *evm.UnsignedImportTx: + for _, input := range tx.ImportedInputs { + utxoID := input.InputID() + if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { + return err + } + } + + b.accountsLock.Lock() + defer b.accountsLock.Unlock() + + for _, output := range tx.Outs { + account, ok := b.accounts[output.Address] + if !ok { + continue + } + + balance := new(big.Int).SetUint64(output.Amount) + balance.Mul(balance, avaxConversionRate) + account.Balance.Add(account.Balance, balance) + } + case *evm.UnsignedExportTx: + txID := tx.ID() + for i, out := range tx.ExportedOutputs { + err := b.AddUTXO( + ctx, + tx.DestinationChain, + &avax.UTXO{ + UTXOID: avax.UTXOID{ + TxID: txID, + OutputIndex: uint32(i), + }, + Asset: avax.Asset{ID: out.AssetID()}, + Out: out.Out, + }, + ) + if err != nil { + return err + } + } + + b.accountsLock.Lock() + defer b.accountsLock.Unlock() + + for _, input := range tx.Ins { + account, ok := b.accounts[input.Address] + if !ok { + continue + } + + balance := new(big.Int).SetUint64(input.Amount) + balance.Mul(balance, avaxConversionRate) + if account.Balance.Cmp(balance) == -1 { + return errInsufficientFunds + } + account.Balance.Sub(account.Balance, balance) + + newNonce, err := math.Add64(input.Nonce, 1) + if err != nil { + return err + } + account.Nonce = newNonce + } + default: + return fmt.Errorf("%w: %T", errUnknownTxType, tx) + } + return nil +} + +func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { + b.accountsLock.RLock() + defer b.accountsLock.RUnlock() + + account, exists := b.accounts[addr] + if !exists { + return nil, database.ErrNotFound + } + return account.Balance, nil +} + +func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { + b.accountsLock.RLock() + defer b.accountsLock.RUnlock() + + account, exists := b.accounts[addr] + if !exists { + return 0, database.ErrNotFound + } + return account.Nonce, nil +} diff --git a/wallet/chain/c/builder.go b/wallet/chain/c/builder.go index c51d2647777e..d2d088e88a53 100644 --- a/wallet/chain/c/builder.go +++ b/wallet/chain/c/builder.go @@ -3,399 +3,399 @@ package c -// import ( -// "errors" -// "math/big" - -// stdcontext "context" - -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils" -// "github.com/ava-labs/avalanchego/utils/math" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// const avaxConversionRateInt = 1_000_000_000 - -// var ( -// _ Builder = (*builder)(nil) - -// errInsufficientFunds = errors.New("insufficient funds") - -// // avaxConversionRate is the conversion rate between the smallest -// // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest -// // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. -// // -// // This is only required for AVAX because the denomination of 1 AVAX is 9 -// // decimal places on the X and P chains, but is 18 decimal places within the -// // EVM. -// avaxConversionRate = big.NewInt(avaxConversionRateInt) -// ) - -// // Builder provides a convenient interface for building unsigned C-chain -// // transactions. -// type Builder interface { -// // GetBalance calculates the amount of AVAX that this builder has control -// // over. -// GetBalance( -// options ...common.Option, -// ) (*big.Int, error) - -// // GetImportableBalance calculates the amount of AVAX that this builder -// // could import from the provided chain. -// // -// // - [chainID] specifies the chain the funds are from. -// GetImportableBalance( -// chainID ids.ID, -// options ...common.Option, -// ) (uint64, error) - -// // NewImportTx creates an import transaction that attempts to consume all -// // the available UTXOs and import the funds to [to]. -// // -// // - [chainID] specifies the chain to be importing funds from. -// // - [to] specifies where to send the imported funds to. -// // - [baseFee] specifies the fee price willing to be paid by this tx. -// NewImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedImportTx, error) - -// // NewExportTx creates an export transaction that attempts to send all the -// // provided [outputs] to the requested [chainID]. -// // -// // - [chainID] specifies the chain to be exporting the funds to. -// // - [outputs] specifies the outputs to send to the [chainID]. -// // - [baseFee] specifies the fee price willing to be paid by this tx. -// NewExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedExportTx, error) -// } - -// // BuilderBackend specifies the required information needed to build unsigned -// // C-chain transactions. -// type BuilderBackend interface { -// Context - -// UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) -// Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) -// Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) -// } - -// type builder struct { -// avaxAddrs set.Set[ids.ShortID] -// ethAddrs set.Set[ethcommon.Address] -// backend BuilderBackend -// } - -// // NewBuilder returns a new transaction builder. -// // -// // - [avaxAddrs] is the set of addresses in the AVAX format that the builder -// // assumes can be used when signing the transactions in the future. -// // - [ethAddrs] is the set of addresses in the Eth format that the builder -// // assumes can be used when signing the transactions in the future. -// // - [backend] provides the required access to the chain's context and state -// // to build out the transactions. -// func NewBuilder( -// avaxAddrs set.Set[ids.ShortID], -// ethAddrs set.Set[ethcommon.Address], -// backend BuilderBackend, -// ) Builder { -// return &builder{ -// avaxAddrs: avaxAddrs, -// ethAddrs: ethAddrs, -// backend: backend, -// } -// } - -// func (b *builder) GetBalance( -// options ...common.Option, -// ) (*big.Int, error) { -// var ( -// ops = common.NewOptions(options) -// ctx = ops.Context() -// addrs = ops.EthAddresses(b.ethAddrs) -// totalBalance = new(big.Int) -// ) -// for addr := range addrs { -// balance, err := b.backend.Balance(ctx, addr) -// if err != nil { -// return nil, err -// } -// totalBalance.Add(totalBalance, balance) -// } - -// return totalBalance, nil -// } - -// func (b *builder) GetImportableBalance( -// chainID ids.ID, -// options ...common.Option, -// ) (uint64, error) { -// ops := common.NewOptions(options) -// utxos, err := b.backend.UTXOs(ops.Context(), chainID) -// if err != nil { -// return 0, err -// } - -// var ( -// addrs = ops.Addresses(b.avaxAddrs) -// minIssuanceTime = ops.MinIssuanceTime() -// avaxAssetID = b.backend.AVAXAssetID() -// balance uint64 -// ) -// for _, utxo := range utxos { -// amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) -// if !ok { -// continue -// } - -// newBalance, err := math.Add64(balance, amount) -// if err != nil { -// return 0, err -// } -// balance = newBalance -// } - -// return balance, nil -// } - -// func (b *builder) NewImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedImportTx, error) { -// ops := common.NewOptions(options) -// utxos, err := b.backend.UTXOs(ops.Context(), chainID) -// if err != nil { -// return nil, err -// } - -// var ( -// addrs = ops.Addresses(b.avaxAddrs) -// minIssuanceTime = ops.MinIssuanceTime() -// avaxAssetID = b.backend.AVAXAssetID() - -// importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) -// importedAmount uint64 -// ) -// for _, utxo := range utxos { -// amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) -// if !ok { -// continue -// } - -// importedInputs = append(importedInputs, &avax.TransferableInput{ -// UTXOID: utxo.UTXOID, -// Asset: utxo.Asset, -// In: &secp256k1fx.TransferInput{ -// Amt: amount, -// Input: secp256k1fx.Input{ -// SigIndices: inputSigIndices, -// }, -// }, -// }) - -// newImportedAmount, err := math.Add64(importedAmount, amount) -// if err != nil { -// return nil, err -// } -// importedAmount = newImportedAmount -// } - -// utils.Sort(importedInputs) -// tx := &evm.UnsignedImportTx{ -// NetworkID: b.backend.NetworkID(), -// BlockchainID: b.backend.BlockchainID(), -// SourceChain: chainID, -// ImportedInputs: importedInputs, -// } - -// // We must initialize the bytes of the tx to calculate the initial cost -// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} -// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { -// return nil, err -// } - -// gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) -// if err != nil { -// return nil, err -// } -// gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas - -// txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) -// if err != nil { -// return nil, err -// } - -// if importedAmount <= txFee { -// return nil, errInsufficientFunds -// } - -// tx.Outs = []evm.EVMOutput{{ -// Address: to, -// Amount: importedAmount - txFee, -// AssetID: avaxAssetID, -// }} -// return tx, nil -// } - -// func (b *builder) NewExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedExportTx, error) { -// var ( -// avaxAssetID = b.backend.AVAXAssetID() -// exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) -// exportedAmount uint64 -// ) -// for i, output := range outputs { -// exportedOutputs[i] = &avax.TransferableOutput{ -// Asset: avax.Asset{ID: avaxAssetID}, -// Out: output, -// } - -// newExportedAmount, err := math.Add64(exportedAmount, output.Amt) -// if err != nil { -// return nil, err -// } -// exportedAmount = newExportedAmount -// } - -// avax.SortTransferableOutputs(exportedOutputs, evm.Codec) -// tx := &evm.UnsignedExportTx{ -// NetworkID: b.backend.NetworkID(), -// BlockchainID: b.backend.BlockchainID(), -// DestinationChain: chainID, -// ExportedOutputs: exportedOutputs, -// } - -// // We must initialize the bytes of the tx to calculate the initial cost -// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} -// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { -// return nil, err -// } - -// cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) -// if err != nil { -// return nil, err -// } - -// initialFee, err := evm.CalculateDynamicFee(cost, baseFee) -// if err != nil { -// return nil, err -// } - -// amountToConsume, err := math.Add64(exportedAmount, initialFee) -// if err != nil { -// return nil, err -// } - -// var ( -// ops = common.NewOptions(options) -// ctx = ops.Context() -// addrs = ops.EthAddresses(b.ethAddrs) -// inputs = make([]evm.EVMInput, 0, addrs.Len()) -// ) -// for addr := range addrs { -// if amountToConsume == 0 { -// break -// } - -// prevFee, err := evm.CalculateDynamicFee(cost, baseFee) -// if err != nil { -// return nil, err -// } - -// newCost := cost + evm.EVMInputGas -// newFee, err := evm.CalculateDynamicFee(newCost, baseFee) -// if err != nil { -// return nil, err -// } - -// additionalFee := newFee - prevFee - -// balance, err := b.backend.Balance(ctx, addr) -// if err != nil { -// return nil, err -// } - -// // Since the asset is AVAX, we divide by the avaxConversionRate to -// // convert back to the correct denomination of AVAX that can be -// // exported. -// avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() - -// // If the balance for [addr] is insufficient to cover the additional -// // cost of adding an input to the transaction, skip adding the input -// // altogether. -// if avaxBalance <= additionalFee { -// continue -// } - -// // Update the cost for the next iteration -// cost = newCost - -// amountToConsume, err = math.Add64(amountToConsume, additionalFee) -// if err != nil { -// return nil, err -// } - -// nonce, err := b.backend.Nonce(ctx, addr) -// if err != nil { -// return nil, err -// } - -// inputAmount := math.Min(amountToConsume, avaxBalance) -// inputs = append(inputs, evm.EVMInput{ -// Address: addr, -// Amount: inputAmount, -// AssetID: avaxAssetID, -// Nonce: nonce, -// }) -// amountToConsume -= inputAmount -// } - -// if amountToConsume > 0 { -// return nil, errInsufficientFunds -// } - -// utils.Sort(inputs) -// tx.Ins = inputs -// return tx, nil -// } - -// func getSpendableAmount( -// utxo *avax.UTXO, -// addrs set.Set[ids.ShortID], -// minIssuanceTime uint64, -// avaxAssetID ids.ID, -// ) (uint64, []uint32, bool) { -// if utxo.Asset.ID != avaxAssetID { -// // Only AVAX can be imported -// return 0, nil, false -// } - -// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) -// if !ok { -// // Can't import an unknown transfer output type -// return 0, nil, false -// } - -// inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) -// return out.Amt, inputSigIndices, ok -// } +import ( + "errors" + "math/big" + + stdcontext "context" + + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils" + "github.com/ava-labs/avalanchego/utils/math" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +const avaxConversionRateInt = 1_000_000_000 + +var ( + _ Builder = (*builder)(nil) + + errInsufficientFunds = errors.New("insufficient funds") + + // avaxConversionRate is the conversion rate between the smallest + // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest + // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. + // + // This is only required for AVAX because the denomination of 1 AVAX is 9 + // decimal places on the X and P chains, but is 18 decimal places within the + // EVM. + avaxConversionRate = big.NewInt(avaxConversionRateInt) +) + +// Builder provides a convenient interface for building unsigned C-chain +// transactions. +type Builder interface { + // GetBalance calculates the amount of AVAX that this builder has control + // over. + GetBalance( + options ...common.Option, + ) (*big.Int, error) + + // GetImportableBalance calculates the amount of AVAX that this builder + // could import from the provided chain. + // + // - [chainID] specifies the chain the funds are from. + GetImportableBalance( + chainID ids.ID, + options ...common.Option, + ) (uint64, error) + + // NewImportTx creates an import transaction that attempts to consume all + // the available UTXOs and import the funds to [to]. + // + // - [chainID] specifies the chain to be importing funds from. + // - [to] specifies where to send the imported funds to. + // - [baseFee] specifies the fee price willing to be paid by this tx. + NewImportTx( + chainID ids.ID, + to ethcommon.Address, + baseFee *big.Int, + options ...common.Option, + ) (*evm.UnsignedImportTx, error) + + // NewExportTx creates an export transaction that attempts to send all the + // provided [outputs] to the requested [chainID]. + // + // - [chainID] specifies the chain to be exporting the funds to. + // - [outputs] specifies the outputs to send to the [chainID]. + // - [baseFee] specifies the fee price willing to be paid by this tx. + NewExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + baseFee *big.Int, + options ...common.Option, + ) (*evm.UnsignedExportTx, error) +} + +// BuilderBackend specifies the required information needed to build unsigned +// C-chain transactions. +type BuilderBackend interface { + Context + + UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) + Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) + Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) +} + +type builder struct { + avaxAddrs set.Set[ids.ShortID] + ethAddrs set.Set[ethcommon.Address] + backend BuilderBackend +} + +// NewBuilder returns a new transaction builder. +// +// - [avaxAddrs] is the set of addresses in the AVAX format that the builder +// assumes can be used when signing the transactions in the future. +// - [ethAddrs] is the set of addresses in the Eth format that the builder +// assumes can be used when signing the transactions in the future. +// - [backend] provides the required access to the chain's context and state +// to build out the transactions. +func NewBuilder( + avaxAddrs set.Set[ids.ShortID], + ethAddrs set.Set[ethcommon.Address], + backend BuilderBackend, +) Builder { + return &builder{ + avaxAddrs: avaxAddrs, + ethAddrs: ethAddrs, + backend: backend, + } +} + +func (b *builder) GetBalance( + options ...common.Option, +) (*big.Int, error) { + var ( + ops = common.NewOptions(options) + ctx = ops.Context() + addrs = ops.EthAddresses(b.ethAddrs) + totalBalance = new(big.Int) + ) + for addr := range addrs { + balance, err := b.backend.Balance(ctx, addr) + if err != nil { + return nil, err + } + totalBalance.Add(totalBalance, balance) + } + + return totalBalance, nil +} + +func (b *builder) GetImportableBalance( + chainID ids.ID, + options ...common.Option, +) (uint64, error) { + ops := common.NewOptions(options) + utxos, err := b.backend.UTXOs(ops.Context(), chainID) + if err != nil { + return 0, err + } + + var ( + addrs = ops.Addresses(b.avaxAddrs) + minIssuanceTime = ops.MinIssuanceTime() + avaxAssetID = b.backend.AVAXAssetID() + balance uint64 + ) + for _, utxo := range utxos { + amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) + if !ok { + continue + } + + newBalance, err := math.Add64(balance, amount) + if err != nil { + return 0, err + } + balance = newBalance + } + + return balance, nil +} + +func (b *builder) NewImportTx( + chainID ids.ID, + to ethcommon.Address, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedImportTx, error) { + ops := common.NewOptions(options) + utxos, err := b.backend.UTXOs(ops.Context(), chainID) + if err != nil { + return nil, err + } + + var ( + addrs = ops.Addresses(b.avaxAddrs) + minIssuanceTime = ops.MinIssuanceTime() + avaxAssetID = b.backend.AVAXAssetID() + + importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) + importedAmount uint64 + ) + for _, utxo := range utxos { + amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) + if !ok { + continue + } + + importedInputs = append(importedInputs, &avax.TransferableInput{ + UTXOID: utxo.UTXOID, + Asset: utxo.Asset, + In: &secp256k1fx.TransferInput{ + Amt: amount, + Input: secp256k1fx.Input{ + SigIndices: inputSigIndices, + }, + }, + }) + + newImportedAmount, err := math.Add64(importedAmount, amount) + if err != nil { + return nil, err + } + importedAmount = newImportedAmount + } + + utils.Sort(importedInputs) + tx := &evm.UnsignedImportTx{ + NetworkID: b.backend.NetworkID(), + BlockchainID: b.backend.BlockchainID(), + SourceChain: chainID, + ImportedInputs: importedInputs, + } + + // We must initialize the bytes of the tx to calculate the initial cost + wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} + if err := wrappedTx.Sign(evm.Codec, nil); err != nil { + return nil, err + } + + gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) + if err != nil { + return nil, err + } + gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas + + txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) + if err != nil { + return nil, err + } + + if importedAmount <= txFee { + return nil, errInsufficientFunds + } + + tx.Outs = []evm.EVMOutput{{ + Address: to, + Amount: importedAmount - txFee, + AssetID: avaxAssetID, + }} + return tx, nil +} + +func (b *builder) NewExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedExportTx, error) { + var ( + avaxAssetID = b.backend.AVAXAssetID() + exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) + exportedAmount uint64 + ) + for i, output := range outputs { + exportedOutputs[i] = &avax.TransferableOutput{ + Asset: avax.Asset{ID: avaxAssetID}, + Out: output, + } + + newExportedAmount, err := math.Add64(exportedAmount, output.Amt) + if err != nil { + return nil, err + } + exportedAmount = newExportedAmount + } + + avax.SortTransferableOutputs(exportedOutputs, evm.Codec) + tx := &evm.UnsignedExportTx{ + NetworkID: b.backend.NetworkID(), + BlockchainID: b.backend.BlockchainID(), + DestinationChain: chainID, + ExportedOutputs: exportedOutputs, + } + + // We must initialize the bytes of the tx to calculate the initial cost + wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} + if err := wrappedTx.Sign(evm.Codec, nil); err != nil { + return nil, err + } + + cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) + if err != nil { + return nil, err + } + + initialFee, err := evm.CalculateDynamicFee(cost, baseFee) + if err != nil { + return nil, err + } + + amountToConsume, err := math.Add64(exportedAmount, initialFee) + if err != nil { + return nil, err + } + + var ( + ops = common.NewOptions(options) + ctx = ops.Context() + addrs = ops.EthAddresses(b.ethAddrs) + inputs = make([]evm.EVMInput, 0, addrs.Len()) + ) + for addr := range addrs { + if amountToConsume == 0 { + break + } + + prevFee, err := evm.CalculateDynamicFee(cost, baseFee) + if err != nil { + return nil, err + } + + newCost := cost + evm.EVMInputGas + newFee, err := evm.CalculateDynamicFee(newCost, baseFee) + if err != nil { + return nil, err + } + + additionalFee := newFee - prevFee + + balance, err := b.backend.Balance(ctx, addr) + if err != nil { + return nil, err + } + + // Since the asset is AVAX, we divide by the avaxConversionRate to + // convert back to the correct denomination of AVAX that can be + // exported. + avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() + + // If the balance for [addr] is insufficient to cover the additional + // cost of adding an input to the transaction, skip adding the input + // altogether. + if avaxBalance <= additionalFee { + continue + } + + // Update the cost for the next iteration + cost = newCost + + amountToConsume, err = math.Add64(amountToConsume, additionalFee) + if err != nil { + return nil, err + } + + nonce, err := b.backend.Nonce(ctx, addr) + if err != nil { + return nil, err + } + + inputAmount := math.Min(amountToConsume, avaxBalance) + inputs = append(inputs, evm.EVMInput{ + Address: addr, + Amount: inputAmount, + AssetID: avaxAssetID, + Nonce: nonce, + }) + amountToConsume -= inputAmount + } + + if amountToConsume > 0 { + return nil, errInsufficientFunds + } + + utils.Sort(inputs) + tx.Ins = inputs + return tx, nil +} + +func getSpendableAmount( + utxo *avax.UTXO, + addrs set.Set[ids.ShortID], + minIssuanceTime uint64, + avaxAssetID ids.ID, +) (uint64, []uint32, bool) { + if utxo.Asset.ID != avaxAssetID { + // Only AVAX can be imported + return 0, nil, false + } + + out, ok := utxo.Out.(*secp256k1fx.TransferOutput) + if !ok { + // Can't import an unknown transfer output type + return 0, nil, false + } + + inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) + return out.Amt, inputSigIndices, ok +} diff --git a/wallet/chain/c/builder_with_options.go b/wallet/chain/c/builder_with_options.go index 9b7ab8399484..8416dddf9928 100644 --- a/wallet/chain/c/builder_with_options.go +++ b/wallet/chain/c/builder_with_options.go @@ -3,81 +3,81 @@ package c -// import ( -// "math/big" +import ( + "math/big" -// "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/coreth/plugin/evm" -// ethcommon "github.com/ethereum/go-ethereum/common" + ethcommon "github.com/ethereum/go-ethereum/common" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) -// var _ Builder = (*builderWithOptions)(nil) +var _ Builder = (*builderWithOptions)(nil) -// type builderWithOptions struct { -// Builder -// options []common.Option -// } +type builderWithOptions struct { + Builder + options []common.Option +} -// // NewBuilderWithOptions returns a new transaction builder that will use the -// // given options by default. -// // -// // - [builder] is the builder that will be called to perform the underlying -// // operations. -// // - [options] will be provided to the builder in addition to the options -// // provided in the method calls. -// func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { -// return &builderWithOptions{ -// Builder: builder, -// options: options, -// } -// } +// NewBuilderWithOptions returns a new transaction builder that will use the +// given options by default. +// +// - [builder] is the builder that will be called to perform the underlying +// operations. +// - [options] will be provided to the builder in addition to the options +// provided in the method calls. +func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { + return &builderWithOptions{ + Builder: builder, + options: options, + } +} -// func (b *builderWithOptions) GetBalance( -// options ...common.Option, -// ) (*big.Int, error) { -// return b.Builder.GetBalance( -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) GetBalance( + options ...common.Option, +) (*big.Int, error) { + return b.Builder.GetBalance( + common.UnionOptions(b.options, options)..., + ) +} -// func (b *builderWithOptions) GetImportableBalance( -// chainID ids.ID, -// options ...common.Option, -// ) (uint64, error) { -// return b.Builder.GetImportableBalance( -// chainID, -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) GetImportableBalance( + chainID ids.ID, + options ...common.Option, +) (uint64, error) { + return b.Builder.GetImportableBalance( + chainID, + common.UnionOptions(b.options, options)..., + ) +} -// func (b *builderWithOptions) NewImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedImportTx, error) { -// return b.Builder.NewImportTx( -// chainID, -// to, -// baseFee, -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) NewImportTx( + chainID ids.ID, + to ethcommon.Address, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedImportTx, error) { + return b.Builder.NewImportTx( + chainID, + to, + baseFee, + common.UnionOptions(b.options, options)..., + ) +} -// func (b *builderWithOptions) NewExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedExportTx, error) { -// return b.Builder.NewExportTx( -// chainID, -// outputs, -// baseFee, -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) NewExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedExportTx, error) { + return b.Builder.NewExportTx( + chainID, + outputs, + baseFee, + common.UnionOptions(b.options, options)..., + ) +} diff --git a/wallet/chain/c/context.go b/wallet/chain/c/context.go index 1c01d8fb55c8..d506b42f81fa 100644 --- a/wallet/chain/c/context.go +++ b/wallet/chain/c/context.go @@ -3,81 +3,81 @@ package c -// import ( -// stdcontext "context" +import ( + stdcontext "context" -// "github.com/ava-labs/avalanchego/api/info" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/avm" -// ) + "github.com/ava-labs/avalanchego/api/info" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/avm" +) -// var _ Context = (*context)(nil) +var _ Context = (*context)(nil) -// type Context interface { -// NetworkID() uint32 -// BlockchainID() ids.ID -// AVAXAssetID() ids.ID -// } +type Context interface { + NetworkID() uint32 + BlockchainID() ids.ID + AVAXAssetID() ids.ID +} -// type context struct { -// networkID uint32 -// blockchainID ids.ID -// avaxAssetID ids.ID -// } +type context struct { + networkID uint32 + blockchainID ids.ID + avaxAssetID ids.ID +} -// func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { -// infoClient := info.NewClient(uri) -// xChainClient := avm.NewClient(uri, "X") -// return NewContextFromClients(ctx, infoClient, xChainClient) -// } +func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { + infoClient := info.NewClient(uri) + xChainClient := avm.NewClient(uri, "X") + return NewContextFromClients(ctx, infoClient, xChainClient) +} -// func NewContextFromClients( -// ctx stdcontext.Context, -// infoClient info.Client, -// xChainClient avm.Client, -// ) (Context, error) { -// networkID, err := infoClient.GetNetworkID(ctx) -// if err != nil { -// return nil, err -// } +func NewContextFromClients( + ctx stdcontext.Context, + infoClient info.Client, + xChainClient avm.Client, +) (Context, error) { + networkID, err := infoClient.GetNetworkID(ctx) + if err != nil { + return nil, err + } -// chainID, err := infoClient.GetBlockchainID(ctx, "C") -// if err != nil { -// return nil, err -// } + chainID, err := infoClient.GetBlockchainID(ctx, "C") + if err != nil { + return nil, err + } -// asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") -// if err != nil { -// return nil, err -// } + asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") + if err != nil { + return nil, err + } -// return NewContext( -// networkID, -// chainID, -// asset.AssetID, -// ), nil -// } + return NewContext( + networkID, + chainID, + asset.AssetID, + ), nil +} -// func NewContext( -// networkID uint32, -// blockchainID ids.ID, -// avaxAssetID ids.ID, -// ) Context { -// return &context{ -// networkID: networkID, -// blockchainID: blockchainID, -// avaxAssetID: avaxAssetID, -// } -// } +func NewContext( + networkID uint32, + blockchainID ids.ID, + avaxAssetID ids.ID, +) Context { + return &context{ + networkID: networkID, + blockchainID: blockchainID, + avaxAssetID: avaxAssetID, + } +} -// func (c *context) NetworkID() uint32 { -// return c.networkID -// } +func (c *context) NetworkID() uint32 { + return c.networkID +} -// func (c *context) BlockchainID() ids.ID { -// return c.blockchainID -// } +func (c *context) BlockchainID() ids.ID { + return c.blockchainID +} -// func (c *context) AVAXAssetID() ids.ID { -// return c.avaxAssetID -// } +func (c *context) AVAXAssetID() ids.ID { + return c.avaxAssetID +} diff --git a/wallet/chain/c/signer.go b/wallet/chain/c/signer.go index 4bedc378234b..4fd85ed3b532 100644 --- a/wallet/chain/c/signer.go +++ b/wallet/chain/c/signer.go @@ -3,221 +3,221 @@ package c -// import ( -// "errors" -// "fmt" - -// stdcontext "context" - -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/database" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils/crypto/keychain" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/hashing" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/components/verify" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// ) - -// const version = 0 - -// var ( -// _ Signer = (*txSigner)(nil) - -// errUnknownInputType = errors.New("unknown input type") -// errUnknownCredentialType = errors.New("unknown credential type") -// errUnknownOutputType = errors.New("unknown output type") -// errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") - -// emptySig [secp256k1.SignatureLen]byte -// ) - -// type Signer interface { -// SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) -// SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error -// } - -// type EthKeychain interface { -// // The returned Signer can provide a signature for [addr] -// GetEth(addr ethcommon.Address) (keychain.Signer, bool) -// // Returns the set of addresses for which the accessor keeps an associated -// // signer -// EthAddresses() set.Set[ethcommon.Address] -// } - -// type SignerBackend interface { -// GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) -// } - -// type txSigner struct { -// avaxKC keychain.Keychain -// ethKC EthKeychain -// backend SignerBackend -// } - -// func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { -// return &txSigner{ -// avaxKC: avaxKC, -// ethKC: ethKC, -// backend: backend, -// } -// } - -// func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { -// tx := &evm.Tx{UnsignedAtomicTx: utx} -// return tx, s.SignAtomic(ctx, tx) -// } - -// func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { -// switch utx := tx.UnsignedAtomicTx.(type) { -// case *evm.UnsignedImportTx: -// signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) -// if err != nil { -// return err -// } -// return sign(tx, true, signers) -// case *evm.UnsignedExportTx: -// signers := s.getExportSigners(utx.Ins) -// return sign(tx, true, signers) -// default: -// return fmt.Errorf("%w: %T", errUnknownTxType, tx) -// } -// } - -// func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { -// txSigners := make([][]keychain.Signer, len(ins)) -// for credIndex, transferInput := range ins { -// input, ok := transferInput.In.(*secp256k1fx.TransferInput) -// if !ok { -// return nil, errUnknownInputType -// } - -// inputSigners := make([]keychain.Signer, len(input.SigIndices)) -// txSigners[credIndex] = inputSigners - -// utxoID := transferInput.InputID() -// utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) -// if err == database.ErrNotFound { -// // If we don't have access to the UTXO, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// if err != nil { -// return nil, err -// } - -// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) -// if !ok { -// return nil, errUnknownOutputType -// } - -// for sigIndex, addrIndex := range input.SigIndices { -// if addrIndex >= uint32(len(out.Addrs)) { -// return nil, errInvalidUTXOSigIndex -// } - -// addr := out.Addrs[addrIndex] -// key, ok := s.avaxKC.Get(addr) -// if !ok { -// // If we don't have access to the key, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// inputSigners[sigIndex] = key -// } -// } -// return txSigners, nil -// } - -// func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { -// txSigners := make([][]keychain.Signer, len(ins)) -// for credIndex, input := range ins { -// inputSigners := make([]keychain.Signer, 1) -// txSigners[credIndex] = inputSigners - -// key, ok := s.ethKC.GetEth(input.Address) -// if !ok { -// // If we don't have access to the key, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// inputSigners[0] = key -// } -// return txSigners -// } - -// // TODO: remove [signHash] after the ledger supports signing all transactions. -// func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { -// unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) -// if err != nil { -// return fmt.Errorf("couldn't marshal unsigned tx: %w", err) -// } -// unsignedHash := hashing.ComputeHash256(unsignedBytes) - -// if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { -// tx.Creds = make([]verify.Verifiable, expectedLen) -// } - -// sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) -// for credIndex, inputSigners := range txSigners { -// credIntf := tx.Creds[credIndex] -// if credIntf == nil { -// credIntf = &secp256k1fx.Credential{} -// tx.Creds[credIndex] = credIntf -// } - -// cred, ok := credIntf.(*secp256k1fx.Credential) -// if !ok { -// return errUnknownCredentialType -// } -// if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { -// cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) -// } - -// for sigIndex, signer := range inputSigners { -// if signer == nil { -// // If we don't have access to the key, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// addr := signer.Address() -// if sig := cred.Sigs[sigIndex]; sig != emptySig { -// // If this signature has already been populated, we can just -// // copy the needed signature for the future. -// sigCache[addr] = sig -// continue -// } - -// if sig, exists := sigCache[addr]; exists { -// // If this key has already produced a signature, we can just -// // copy the previous signature. -// cred.Sigs[sigIndex] = sig -// continue -// } - -// var sig []byte -// if signHash { -// sig, err = signer.SignHash(unsignedHash) -// } else { -// sig, err = signer.Sign(unsignedBytes) -// } -// if err != nil { -// return fmt.Errorf("problem signing tx: %w", err) -// } -// copy(cred.Sigs[sigIndex][:], sig) -// sigCache[addr] = cred.Sigs[sigIndex] -// } -// } - -// signedBytes, err := evm.Codec.Marshal(version, tx) -// if err != nil { -// return fmt.Errorf("couldn't marshal tx: %w", err) -// } -// tx.Initialize(unsignedBytes, signedBytes) -// return nil -// } +import ( + "errors" + "fmt" + + stdcontext "context" + + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/crypto/keychain" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/hashing" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/components/verify" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" +) + +const version = 0 + +var ( + _ Signer = (*txSigner)(nil) + + errUnknownInputType = errors.New("unknown input type") + errUnknownCredentialType = errors.New("unknown credential type") + errUnknownOutputType = errors.New("unknown output type") + errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") + + emptySig [secp256k1.SignatureLen]byte +) + +type Signer interface { + SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) + SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error +} + +type EthKeychain interface { + // The returned Signer can provide a signature for [addr] + GetEth(addr ethcommon.Address) (keychain.Signer, bool) + // Returns the set of addresses for which the accessor keeps an associated + // signer + EthAddresses() set.Set[ethcommon.Address] +} + +type SignerBackend interface { + GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) +} + +type txSigner struct { + avaxKC keychain.Keychain + ethKC EthKeychain + backend SignerBackend +} + +func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { + return &txSigner{ + avaxKC: avaxKC, + ethKC: ethKC, + backend: backend, + } +} + +func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { + tx := &evm.Tx{UnsignedAtomicTx: utx} + return tx, s.SignAtomic(ctx, tx) +} + +func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { + switch utx := tx.UnsignedAtomicTx.(type) { + case *evm.UnsignedImportTx: + signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) + if err != nil { + return err + } + return sign(tx, true, signers) + case *evm.UnsignedExportTx: + signers := s.getExportSigners(utx.Ins) + return sign(tx, true, signers) + default: + return fmt.Errorf("%w: %T", errUnknownTxType, tx) + } +} + +func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { + txSigners := make([][]keychain.Signer, len(ins)) + for credIndex, transferInput := range ins { + input, ok := transferInput.In.(*secp256k1fx.TransferInput) + if !ok { + return nil, errUnknownInputType + } + + inputSigners := make([]keychain.Signer, len(input.SigIndices)) + txSigners[credIndex] = inputSigners + + utxoID := transferInput.InputID() + utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) + if err == database.ErrNotFound { + // If we don't have access to the UTXO, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + if err != nil { + return nil, err + } + + out, ok := utxo.Out.(*secp256k1fx.TransferOutput) + if !ok { + return nil, errUnknownOutputType + } + + for sigIndex, addrIndex := range input.SigIndices { + if addrIndex >= uint32(len(out.Addrs)) { + return nil, errInvalidUTXOSigIndex + } + + addr := out.Addrs[addrIndex] + key, ok := s.avaxKC.Get(addr) + if !ok { + // If we don't have access to the key, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + inputSigners[sigIndex] = key + } + } + return txSigners, nil +} + +func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { + txSigners := make([][]keychain.Signer, len(ins)) + for credIndex, input := range ins { + inputSigners := make([]keychain.Signer, 1) + txSigners[credIndex] = inputSigners + + key, ok := s.ethKC.GetEth(input.Address) + if !ok { + // If we don't have access to the key, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + inputSigners[0] = key + } + return txSigners +} + +// TODO: remove [signHash] after the ledger supports signing all transactions. +func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { + unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) + if err != nil { + return fmt.Errorf("couldn't marshal unsigned tx: %w", err) + } + unsignedHash := hashing.ComputeHash256(unsignedBytes) + + if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { + tx.Creds = make([]verify.Verifiable, expectedLen) + } + + sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) + for credIndex, inputSigners := range txSigners { + credIntf := tx.Creds[credIndex] + if credIntf == nil { + credIntf = &secp256k1fx.Credential{} + tx.Creds[credIndex] = credIntf + } + + cred, ok := credIntf.(*secp256k1fx.Credential) + if !ok { + return errUnknownCredentialType + } + if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { + cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) + } + + for sigIndex, signer := range inputSigners { + if signer == nil { + // If we don't have access to the key, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + addr := signer.Address() + if sig := cred.Sigs[sigIndex]; sig != emptySig { + // If this signature has already been populated, we can just + // copy the needed signature for the future. + sigCache[addr] = sig + continue + } + + if sig, exists := sigCache[addr]; exists { + // If this key has already produced a signature, we can just + // copy the previous signature. + cred.Sigs[sigIndex] = sig + continue + } + + var sig []byte + if signHash { + sig, err = signer.SignHash(unsignedHash) + } else { + sig, err = signer.Sign(unsignedBytes) + } + if err != nil { + return fmt.Errorf("problem signing tx: %w", err) + } + copy(cred.Sigs[sigIndex][:], sig) + sigCache[addr] = cred.Sigs[sigIndex] + } + } + + signedBytes, err := evm.Codec.Marshal(version, tx) + if err != nil { + return fmt.Errorf("couldn't marshal tx: %w", err) + } + tx.Initialize(unsignedBytes, signedBytes) + return nil +} diff --git a/wallet/chain/c/wallet.go b/wallet/chain/c/wallet.go index ebee50a9a958..fb1a83d53dad 100644 --- a/wallet/chain/c/wallet.go +++ b/wallet/chain/c/wallet.go @@ -3,204 +3,204 @@ package c -// import ( -// "errors" -// "math/big" -// "time" - -// "github.com/ava-labs/coreth/ethclient" -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var ( -// _ Wallet = (*wallet)(nil) - -// errNotCommitted = errors.New("not committed") -// ) - -// type Wallet interface { -// Context - -// // Builder returns the builder that will be used to create the transactions. -// Builder() Builder - -// // Signer returns the signer that will be used to sign the transactions. -// Signer() Signer - -// // IssueImportTx creates, signs, and issues an import transaction that -// // attempts to consume all the available UTXOs and import the funds to [to]. -// // -// // - [chainID] specifies the chain to be importing funds from. -// // - [to] specifies where to send the imported funds to. -// IssueImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// options ...common.Option, -// ) (*evm.Tx, error) - -// // IssueExportTx creates, signs, and issues an export transaction that -// // attempts to send all the provided [outputs] to the requested [chainID]. -// // -// // - [chainID] specifies the chain to be exporting the funds to. -// // - [outputs] specifies the outputs to send to the [chainID]. -// IssueExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// options ...common.Option, -// ) (*evm.Tx, error) - -// // IssueUnsignedTx signs and issues the unsigned tx. -// IssueUnsignedAtomicTx( -// utx evm.UnsignedAtomicTx, -// options ...common.Option, -// ) (*evm.Tx, error) - -// // IssueAtomicTx issues the signed tx. -// IssueAtomicTx( -// tx *evm.Tx, -// options ...common.Option, -// ) error -// } - -// func NewWallet( -// builder Builder, -// signer Signer, -// avaxClient evm.Client, -// ethClient ethclient.Client, -// backend Backend, -// ) Wallet { -// return &wallet{ -// Backend: backend, -// builder: builder, -// signer: signer, -// avaxClient: avaxClient, -// ethClient: ethClient, -// } -// } - -// type wallet struct { -// Backend -// builder Builder -// signer Signer -// avaxClient evm.Client -// ethClient ethclient.Client -// } - -// func (w *wallet) Builder() Builder { -// return w.builder -// } - -// func (w *wallet) Signer() Signer { -// return w.signer -// } - -// func (w *wallet) IssueImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// options ...common.Option, -// ) (*evm.Tx, error) { -// baseFee, err := w.baseFee(options) -// if err != nil { -// return nil, err -// } - -// utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) -// if err != nil { -// return nil, err -// } -// return w.IssueUnsignedAtomicTx(utx, options...) -// } - -// func (w *wallet) IssueExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// options ...common.Option, -// ) (*evm.Tx, error) { -// baseFee, err := w.baseFee(options) -// if err != nil { -// return nil, err -// } - -// utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) -// if err != nil { -// return nil, err -// } -// return w.IssueUnsignedAtomicTx(utx, options...) -// } - -// func (w *wallet) IssueUnsignedAtomicTx( -// utx evm.UnsignedAtomicTx, -// options ...common.Option, -// ) (*evm.Tx, error) { -// ops := common.NewOptions(options) -// ctx := ops.Context() -// tx, err := w.signer.SignUnsignedAtomic(ctx, utx) -// if err != nil { -// return nil, err -// } - -// return tx, w.IssueAtomicTx(tx, options...) -// } - -// func (w *wallet) IssueAtomicTx( -// tx *evm.Tx, -// options ...common.Option, -// ) error { -// ops := common.NewOptions(options) -// ctx := ops.Context() -// txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) -// if err != nil { -// return err -// } - -// if f := ops.PostIssuanceFunc(); f != nil { -// f(txID) -// } - -// if ops.AssumeDecided() { -// return w.Backend.AcceptAtomicTx(ctx, tx) -// } - -// pollFrequency := ops.PollFrequency() -// ticker := time.NewTicker(pollFrequency) -// defer ticker.Stop() - -// for { -// status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) -// if err != nil { -// return err -// } - -// switch status { -// case evm.Accepted: -// return w.Backend.AcceptAtomicTx(ctx, tx) -// case evm.Dropped, evm.Unknown: -// return errNotCommitted -// } - -// // The tx is Processing. - -// select { -// case <-ticker.C: -// case <-ctx.Done(): -// return ctx.Err() -// } -// } -// } - -// func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { -// ops := common.NewOptions(options) -// baseFee := ops.BaseFee(nil) -// if baseFee != nil { -// return baseFee, nil -// } - -// ctx := ops.Context() -// return w.ethClient.EstimateBaseFee(ctx) -// } +import ( + "errors" + "math/big" + "time" + + "github.com/ava-labs/coreth/ethclient" + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var ( + _ Wallet = (*wallet)(nil) + + errNotCommitted = errors.New("not committed") +) + +type Wallet interface { + Context + + // Builder returns the builder that will be used to create the transactions. + Builder() Builder + + // Signer returns the signer that will be used to sign the transactions. + Signer() Signer + + // IssueImportTx creates, signs, and issues an import transaction that + // attempts to consume all the available UTXOs and import the funds to [to]. + // + // - [chainID] specifies the chain to be importing funds from. + // - [to] specifies where to send the imported funds to. + IssueImportTx( + chainID ids.ID, + to ethcommon.Address, + options ...common.Option, + ) (*evm.Tx, error) + + // IssueExportTx creates, signs, and issues an export transaction that + // attempts to send all the provided [outputs] to the requested [chainID]. + // + // - [chainID] specifies the chain to be exporting the funds to. + // - [outputs] specifies the outputs to send to the [chainID]. + IssueExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + options ...common.Option, + ) (*evm.Tx, error) + + // IssueUnsignedTx signs and issues the unsigned tx. + IssueUnsignedAtomicTx( + utx evm.UnsignedAtomicTx, + options ...common.Option, + ) (*evm.Tx, error) + + // IssueAtomicTx issues the signed tx. + IssueAtomicTx( + tx *evm.Tx, + options ...common.Option, + ) error +} + +func NewWallet( + builder Builder, + signer Signer, + avaxClient evm.Client, + ethClient ethclient.Client, + backend Backend, +) Wallet { + return &wallet{ + Backend: backend, + builder: builder, + signer: signer, + avaxClient: avaxClient, + ethClient: ethClient, + } +} + +type wallet struct { + Backend + builder Builder + signer Signer + avaxClient evm.Client + ethClient ethclient.Client +} + +func (w *wallet) Builder() Builder { + return w.builder +} + +func (w *wallet) Signer() Signer { + return w.signer +} + +func (w *wallet) IssueImportTx( + chainID ids.ID, + to ethcommon.Address, + options ...common.Option, +) (*evm.Tx, error) { + baseFee, err := w.baseFee(options) + if err != nil { + return nil, err + } + + utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) + if err != nil { + return nil, err + } + return w.IssueUnsignedAtomicTx(utx, options...) +} + +func (w *wallet) IssueExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + options ...common.Option, +) (*evm.Tx, error) { + baseFee, err := w.baseFee(options) + if err != nil { + return nil, err + } + + utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) + if err != nil { + return nil, err + } + return w.IssueUnsignedAtomicTx(utx, options...) +} + +func (w *wallet) IssueUnsignedAtomicTx( + utx evm.UnsignedAtomicTx, + options ...common.Option, +) (*evm.Tx, error) { + ops := common.NewOptions(options) + ctx := ops.Context() + tx, err := w.signer.SignUnsignedAtomic(ctx, utx) + if err != nil { + return nil, err + } + + return tx, w.IssueAtomicTx(tx, options...) +} + +func (w *wallet) IssueAtomicTx( + tx *evm.Tx, + options ...common.Option, +) error { + ops := common.NewOptions(options) + ctx := ops.Context() + txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) + if err != nil { + return err + } + + if f := ops.PostIssuanceFunc(); f != nil { + f(txID) + } + + if ops.AssumeDecided() { + return w.Backend.AcceptAtomicTx(ctx, tx) + } + + pollFrequency := ops.PollFrequency() + ticker := time.NewTicker(pollFrequency) + defer ticker.Stop() + + for { + status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) + if err != nil { + return err + } + + switch status { + case evm.Accepted: + return w.Backend.AcceptAtomicTx(ctx, tx) + case evm.Dropped, evm.Unknown: + return errNotCommitted + } + + // The tx is Processing. + + select { + case <-ticker.C: + case <-ctx.Done(): + return ctx.Err() + } + } +} + +func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { + ops := common.NewOptions(options) + baseFee := ops.BaseFee(nil) + if baseFee != nil { + return baseFee, nil + } + + ctx := ops.Context() + return w.ethClient.EstimateBaseFee(ctx) +} diff --git a/wallet/chain/c/wallet_with_options.go b/wallet/chain/c/wallet_with_options.go index fd69a6d4fd02..7d6193683d49 100644 --- a/wallet/chain/c/wallet_with_options.go +++ b/wallet/chain/c/wallet_with_options.go @@ -3,80 +3,80 @@ package c -// import ( -// "github.com/ava-labs/coreth/plugin/evm" +import ( + "github.com/ava-labs/coreth/plugin/evm" -// ethcommon "github.com/ethereum/go-ethereum/common" + ethcommon "github.com/ethereum/go-ethereum/common" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) -// var _ Wallet = (*walletWithOptions)(nil) +var _ Wallet = (*walletWithOptions)(nil) -// func NewWalletWithOptions( -// wallet Wallet, -// options ...common.Option, -// ) Wallet { -// return &walletWithOptions{ -// Wallet: wallet, -// options: options, -// } -// } +func NewWalletWithOptions( + wallet Wallet, + options ...common.Option, +) Wallet { + return &walletWithOptions{ + Wallet: wallet, + options: options, + } +} -// type walletWithOptions struct { -// Wallet -// options []common.Option -// } +type walletWithOptions struct { + Wallet + options []common.Option +} -// func (w *walletWithOptions) Builder() Builder { -// return NewBuilderWithOptions( -// w.Wallet.Builder(), -// w.options..., -// ) -// } +func (w *walletWithOptions) Builder() Builder { + return NewBuilderWithOptions( + w.Wallet.Builder(), + w.options..., + ) +} -// func (w *walletWithOptions) IssueImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// options ...common.Option, -// ) (*evm.Tx, error) { -// return w.Wallet.IssueImportTx( -// chainID, -// to, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueImportTx( + chainID ids.ID, + to ethcommon.Address, + options ...common.Option, +) (*evm.Tx, error) { + return w.Wallet.IssueImportTx( + chainID, + to, + common.UnionOptions(w.options, options)..., + ) +} -// func (w *walletWithOptions) IssueExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// options ...common.Option, -// ) (*evm.Tx, error) { -// return w.Wallet.IssueExportTx( -// chainID, -// outputs, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + options ...common.Option, +) (*evm.Tx, error) { + return w.Wallet.IssueExportTx( + chainID, + outputs, + common.UnionOptions(w.options, options)..., + ) +} -// func (w *walletWithOptions) IssueUnsignedAtomicTx( -// utx evm.UnsignedAtomicTx, -// options ...common.Option, -// ) (*evm.Tx, error) { -// return w.Wallet.IssueUnsignedAtomicTx( -// utx, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueUnsignedAtomicTx( + utx evm.UnsignedAtomicTx, + options ...common.Option, +) (*evm.Tx, error) { + return w.Wallet.IssueUnsignedAtomicTx( + utx, + common.UnionOptions(w.options, options)..., + ) +} -// func (w *walletWithOptions) IssueAtomicTx( -// tx *evm.Tx, -// options ...common.Option, -// ) error { -// return w.Wallet.IssueAtomicTx( -// tx, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueAtomicTx( + tx *evm.Tx, + options ...common.Option, +) error { + return w.Wallet.IssueAtomicTx( + tx, + common.UnionOptions(w.options, options)..., + ) +} diff --git a/wallet/subnet/primary/api.go b/wallet/subnet/primary/api.go index 3d35fee24e4d..3ac72c217884 100644 --- a/wallet/subnet/primary/api.go +++ b/wallet/subnet/primary/api.go @@ -5,12 +5,12 @@ package primary import ( "context" - // "fmt" + "fmt" - // "github.com/ava-labs/coreth/ethclient" - // "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/coreth/ethclient" + "github.com/ava-labs/coreth/plugin/evm" - // "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common" "github.com/ava-labs/avalanchego/api/info" "github.com/ava-labs/avalanchego/codec" @@ -22,8 +22,7 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm" "github.com/ava-labs/avalanchego/vms/platformvm/txs" - - // "github.com/ava-labs/avalanchego/wallet/chain/c" + "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" ) @@ -60,9 +59,9 @@ type AVAXState struct { PCTX p.Context XClient avm.Client XCTX x.Context - // CClient evm.Client - // CCTX c.Context - UTXOs UTXOs + CClient evm.Client + CCTX c.Context + UTXOs UTXOs } func FetchState( @@ -76,7 +75,7 @@ func FetchState( infoClient := info.NewClient(uri) pClient := platformvm.NewClient(uri) xClient := avm.NewClient(uri, "X") - // cClient := evm.NewCChainClient(uri) + cClient := evm.NewCChainClient(uri) pCTX, err := p.NewContextFromClients(ctx, infoClient, xClient) if err != nil { @@ -88,10 +87,10 @@ func FetchState( return nil, err } - // cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) - // if err != nil { - // return nil, err - // } + cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) + if err != nil { + return nil, err + } utxos := NewUTXOs() addrList := addrs.List() @@ -110,11 +109,11 @@ func FetchState( client: xClient, codec: x.Parser.Codec(), }, - // { - // id: cCTX.BlockchainID(), - // client: cClient, - // codec: evm.Codec, - // }, + { + id: cCTX.BlockchainID(), + client: cClient, + codec: evm.Codec, + }, } for _, destinationChain := range chains { for _, sourceChain := range chains { @@ -137,52 +136,52 @@ func FetchState( PCTX: pCTX, XClient: xClient, XCTX: xCTX, - // CClient: cClient, - // CCTX: cCTX, - UTXOs: utxos, + CClient: cClient, + CCTX: cCTX, + UTXOs: utxos, }, nil } -// type EthState struct { -// Client ethclient.Client -// Accounts map[common.Address]*c.Account -// } - -// func FetchEthState( -// ctx context.Context, -// uri string, -// addrs set.Set[common.Address], -// ) (*EthState, error) { -// path := fmt.Sprintf( -// "%s/ext/%s/C/rpc", -// uri, -// constants.ChainAliasPrefix, -// ) -// client, err := ethclient.Dial(path) -// if err != nil { -// return nil, err -// } - -// accounts := make(map[common.Address]*c.Account, addrs.Len()) -// for addr := range addrs { -// balance, err := client.BalanceAt(ctx, addr, nil) -// if err != nil { -// return nil, err -// } -// nonce, err := client.NonceAt(ctx, addr, nil) -// if err != nil { -// return nil, err -// } -// accounts[addr] = &c.Account{ -// Balance: balance, -// Nonce: nonce, -// } -// } -// return &EthState{ -// Client: client, -// Accounts: accounts, -// }, nil -// } +type EthState struct { + Client ethclient.Client + Accounts map[common.Address]*c.Account +} + +func FetchEthState( + ctx context.Context, + uri string, + addrs set.Set[common.Address], +) (*EthState, error) { + path := fmt.Sprintf( + "%s/ext/%s/C/rpc", + uri, + constants.ChainAliasPrefix, + ) + client, err := ethclient.Dial(path) + if err != nil { + return nil, err + } + + accounts := make(map[common.Address]*c.Account, addrs.Len()) + for addr := range addrs { + balance, err := client.BalanceAt(ctx, addr, nil) + if err != nil { + return nil, err + } + nonce, err := client.NonceAt(ctx, addr, nil) + if err != nil { + return nil, err + } + accounts[addr] = &c.Account{ + Balance: balance, + Nonce: nonce, + } + } + return &EthState{ + Client: client, + Accounts: accounts, + }, nil +} // AddAllUTXOs fetches all the UTXOs referenced by [addresses] that were sent // from [sourceChainID] to [destinationChainID] from the [client]. It then uses diff --git a/wallet/subnet/primary/example_test.go b/wallet/subnet/primary/example_test.go index 4a73e8c070b2..483c049d4ac0 100644 --- a/wallet/subnet/primary/example_test.go +++ b/wallet/subnet/primary/example_test.go @@ -30,7 +30,7 @@ func ExampleWallet() { wallet, err := MakeWallet(ctx, &WalletConfig{ URI: LocalAPIURI, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet with: %s\n", err) diff --git a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go index 21c081d2982b..d5e8ce422307 100644 --- a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go @@ -46,9 +46,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/add-primary-validator/main.go b/wallet/subnet/primary/examples/add-primary-validator/main.go index 13c28f995f63..a56dae23db3a 100644 --- a/wallet/subnet/primary/examples/add-primary-validator/main.go +++ b/wallet/subnet/primary/examples/add-primary-validator/main.go @@ -45,7 +45,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/c-chain-export/main.go b/wallet/subnet/primary/examples/c-chain-export/main.go index a6b9a0c810b8..fec55c899feb 100644 --- a/wallet/subnet/primary/examples/c-chain-export/main.go +++ b/wallet/subnet/primary/examples/c-chain-export/main.go @@ -3,70 +3,70 @@ package main -// import ( -// "context" -// "log" -// "time" +import ( + "context" + "log" + "time" -// "github.com/ava-labs/avalanchego/genesis" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary" -// ) + "github.com/ava-labs/avalanchego/genesis" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary" +) -// func main() { -// key := genesis.EWOQKey -// uri := primary.LocalAPIURI -// kc := secp256k1fx.NewKeychain(key) -// avaxAddr := key.Address() +func main() { + key := genesis.EWOQKey + uri := primary.LocalAPIURI + kc := secp256k1fx.NewKeychain(key) + avaxAddr := key.Address() -// ctx := context.Background() + ctx := context.Background() -// // MakeWallet fetches the available UTXOs owned by [kc] on the network that -// // [uri] is hosting. -// walletSyncStartTime := time.Now() -// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ -// URI: uri, -// AVAXKeychain: kc, -// EthKeychain: kc, -// }) -// if err != nil { -// log.Fatalf("failed to initialize wallet: %s\n", err) -// } -// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) + // MakeWallet fetches the available UTXOs owned by [kc] on the network that + // [uri] is hosting. + walletSyncStartTime := time.Now() + wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, + }) + if err != nil { + log.Fatalf("failed to initialize wallet: %s\n", err) + } + log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) -// // Get the P-chain wallet -// pWallet := wallet.P() -// cWallet := wallet.C() + // Get the P-chain wallet + pWallet := wallet.P() + cWallet := wallet.C() -// // Pull out useful constants to use when issuing transactions. -// cChainID := cWallet.BlockchainID() -// owner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// avaxAddr, -// }, -// } + // Pull out useful constants to use when issuing transactions. + cChainID := cWallet.BlockchainID() + owner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + avaxAddr, + }, + } -// exportStartTime := time.Now() -// exportTx, err := cWallet.IssueExportTx( -// constants.PlatformChainID, -// []*secp256k1fx.TransferOutput{{ -// Amt: units.Avax, -// OutputOwners: owner, -// }}, -// ) -// if err != nil { -// log.Fatalf("failed to issue export transaction: %s\n", err) -// } -// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) + exportStartTime := time.Now() + exportTx, err := cWallet.IssueExportTx( + constants.PlatformChainID, + []*secp256k1fx.TransferOutput{{ + Amt: units.Avax, + OutputOwners: owner, + }}, + ) + if err != nil { + log.Fatalf("failed to issue export transaction: %s\n", err) + } + log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) -// importStartTime := time.Now() -// importTx, err := pWallet.IssueImportTx(cChainID, &owner) -// if err != nil { -// log.Fatalf("failed to issue import transaction: %s\n", err) -// } -// log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) -// } + importStartTime := time.Now() + importTx, err := pWallet.IssueImportTx(cChainID, &owner) + if err != nil { + log.Fatalf("failed to issue import transaction: %s\n", err) + } + log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) +} diff --git a/wallet/subnet/primary/examples/c-chain-import/main.go b/wallet/subnet/primary/examples/c-chain-import/main.go index 2d9b8a244cb0..b4dc4e603eb3 100644 --- a/wallet/subnet/primary/examples/c-chain-import/main.go +++ b/wallet/subnet/primary/examples/c-chain-import/main.go @@ -3,75 +3,75 @@ package main -// import ( -// "context" -// "log" -// "time" +import ( + "context" + "log" + "time" -// "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/coreth/plugin/evm" -// "github.com/ava-labs/avalanchego/genesis" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary" -// ) + "github.com/ava-labs/avalanchego/genesis" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary" +) -// func main() { -// key := genesis.EWOQKey -// uri := primary.LocalAPIURI -// kc := secp256k1fx.NewKeychain(key) -// avaxAddr := key.Address() -// ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) +func main() { + key := genesis.EWOQKey + uri := primary.LocalAPIURI + kc := secp256k1fx.NewKeychain(key) + avaxAddr := key.Address() + ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) -// ctx := context.Background() + ctx := context.Background() -// // MakeWallet fetches the available UTXOs owned by [kc] on the network that -// // [uri] is hosting. -// walletSyncStartTime := time.Now() -// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ -// URI: uri, -// AVAXKeychain: kc, -// EthKeychain: kc, -// }) -// if err != nil { -// log.Fatalf("failed to initialize wallet: %s\n", err) -// } -// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) + // MakeWallet fetches the available UTXOs owned by [kc] on the network that + // [uri] is hosting. + walletSyncStartTime := time.Now() + wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, + }) + if err != nil { + log.Fatalf("failed to initialize wallet: %s\n", err) + } + log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) -// // Get the P-chain wallet -// pWallet := wallet.P() -// cWallet := wallet.C() + // Get the P-chain wallet + pWallet := wallet.P() + cWallet := wallet.C() -// // Pull out useful constants to use when issuing transactions. -// cChainID := cWallet.BlockchainID() -// avaxAssetID := cWallet.AVAXAssetID() -// owner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// avaxAddr, -// }, -// } + // Pull out useful constants to use when issuing transactions. + cChainID := cWallet.BlockchainID() + avaxAssetID := cWallet.AVAXAssetID() + owner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + avaxAddr, + }, + } -// exportStartTime := time.Now() -// exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ -// Asset: avax.Asset{ID: avaxAssetID}, -// Out: &secp256k1fx.TransferOutput{ -// Amt: units.Avax, -// OutputOwners: owner, -// }, -// }}) -// if err != nil { -// log.Fatalf("failed to issue export transaction: %s\n", err) -// } -// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) + exportStartTime := time.Now() + exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ + Asset: avax.Asset{ID: avaxAssetID}, + Out: &secp256k1fx.TransferOutput{ + Amt: units.Avax, + OutputOwners: owner, + }, + }}) + if err != nil { + log.Fatalf("failed to issue export transaction: %s\n", err) + } + log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) -// importStartTime := time.Now() -// importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) -// if err != nil { -// log.Fatalf("failed to issue import transaction: %s\n", err) -// } -// log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) -// } + importStartTime := time.Now() + importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) + if err != nil { + log.Fatalf("failed to issue import transaction: %s\n", err) + } + log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) +} diff --git a/wallet/subnet/primary/examples/create-asset/main.go b/wallet/subnet/primary/examples/create-asset/main.go index 0bccfbb5fc52..30804f083df6 100644 --- a/wallet/subnet/primary/examples/create-asset/main.go +++ b/wallet/subnet/primary/examples/create-asset/main.go @@ -30,7 +30,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-chain/main.go b/wallet/subnet/primary/examples/create-chain/main.go index 521a3cca53cf..5e6898a1b649 100644 --- a/wallet/subnet/primary/examples/create-chain/main.go +++ b/wallet/subnet/primary/examples/create-chain/main.go @@ -41,9 +41,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/create-locked-stakeable/main.go b/wallet/subnet/primary/examples/create-locked-stakeable/main.go index 92f1b5cb0e1b..e688968e9e8a 100644 --- a/wallet/subnet/primary/examples/create-locked-stakeable/main.go +++ b/wallet/subnet/primary/examples/create-locked-stakeable/main.go @@ -39,7 +39,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-subnet/main.go b/wallet/subnet/primary/examples/create-subnet/main.go index 3e8d69bc016a..add98ea7931c 100644 --- a/wallet/subnet/primary/examples/create-subnet/main.go +++ b/wallet/subnet/primary/examples/create-subnet/main.go @@ -28,7 +28,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/remove-subnet-validator/main.go b/wallet/subnet/primary/examples/remove-subnet-validator/main.go index 46f4b85124db..2842c7c0a790 100644 --- a/wallet/subnet/primary/examples/remove-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/remove-subnet-validator/main.go @@ -38,9 +38,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/wallet.go b/wallet/subnet/primary/wallet.go index ae5e4202a099..54de390d029c 100644 --- a/wallet/subnet/primary/wallet.go +++ b/wallet/subnet/primary/wallet.go @@ -11,8 +11,7 @@ import ( "github.com/ava-labs/avalanchego/utils/crypto/keychain" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/platformvm/txs" - - // "github.com/ava-labs/avalanchego/wallet/chain/c" + "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" @@ -24,13 +23,13 @@ var _ Wallet = (*wallet)(nil) type Wallet interface { P() p.Wallet X() x.Wallet - // C() c.Wallet + C() c.Wallet } type wallet struct { p p.Wallet x x.Wallet - // c c.Wallet + c c.Wallet } func (w *wallet) P() p.Wallet { @@ -41,16 +40,16 @@ func (w *wallet) X() x.Wallet { return w.x } -// func (w *wallet) C() c.Wallet { -// return w.c -// } +func (w *wallet) C() c.Wallet { + return w.c +} // Creates a new default wallet -func NewWallet(p p.Wallet, x x.Wallet /*, c c.Wallet*/) Wallet { +func NewWallet(p p.Wallet, x x.Wallet, c c.Wallet) Wallet { return &wallet{ p: p, x: x, - // c: c, + c: c, } } @@ -59,7 +58,7 @@ func NewWalletWithOptions(w Wallet, options ...common.Option) Wallet { return NewWallet( p.NewWalletWithOptions(w.P(), options...), x.NewWalletWithOptions(w.X(), options...), - // c.NewWalletWithOptions(w.C(), options...), + c.NewWalletWithOptions(w.C(), options...), ) } @@ -68,7 +67,7 @@ type WalletConfig struct { URI string // required // Keys to use for signing all transactions. AVAXKeychain keychain.Keychain // required - // EthKeychain c.EthKeychain // required + EthKeychain c.EthKeychain // required // Set of P-chain transactions that the wallet should know about to be able // to generate transactions. PChainTxs map[ids.ID]*txs.Tx // optional @@ -94,11 +93,11 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { return nil, err } - // ethAddrs := config.EthKeychain.EthAddresses() - // ethState, err := FetchEthState(ctx, config.URI, ethAddrs) - // if err != nil { - // return nil, err - // } + ethAddrs := config.EthKeychain.EthAddresses() + ethState, err := FetchEthState(ctx, config.URI, ethAddrs) + if err != nil { + return nil, err + } pChainTxs := config.PChainTxs if pChainTxs == nil { @@ -128,15 +127,15 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { xBuilder := x.NewBuilder(avaxAddrs, xBackend) xSigner := x.NewSigner(config.AVAXKeychain, xBackend) - // cChainID := avaxState.CCTX.BlockchainID() - // cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) - // cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) - // cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) - // cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) + cChainID := avaxState.CCTX.BlockchainID() + cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) + cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) + cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) + cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) return NewWallet( p.NewWallet(pBuilder, pSigner, avaxState.PClient, pBackend), x.NewWallet(xBuilder, xSigner, avaxState.XClient, xBackend), - // c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), + c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), ), nil } From 8c125ff557c36032abfe208b8b39a0d658a4c007 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 30 Oct 2023 12:27:36 +0100 Subject: [PATCH 12/36] wip: block backfilling UTs --- .../transitive_block_backfilling_test.go | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 snow/engine/snowman/transitive_block_backfilling_test.go diff --git a/snow/engine/snowman/transitive_block_backfilling_test.go b/snow/engine/snowman/transitive_block_backfilling_test.go new file mode 100644 index 000000000000..a3f80061bef1 --- /dev/null +++ b/snow/engine/snowman/transitive_block_backfilling_test.go @@ -0,0 +1,86 @@ +// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package snowman + +import ( + "context" + "testing" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/snow/choices" + "github.com/ava-labs/avalanchego/snow/consensus/snowman" + "github.com/ava-labs/avalanchego/snow/engine/common" + "github.com/ava-labs/avalanchego/snow/engine/snowman/block" + "github.com/ava-labs/avalanchego/snow/validators" + "github.com/stretchr/testify/require" +) + +type fullVM struct { + *block.TestVM + *block.TestStateSyncableVM +} + +func TestGetAncestorsRequestIssuedIfStateSyncVMEnabledBlockBackfilling(t *testing.T) { + require := require.New(t) + engCfg := DefaultConfigs() + + var ( + vm = &fullVM{ + TestVM: &block.TestVM{ + TestVM: common.TestVM{ + T: t, + }, + }, + TestStateSyncableVM: &block.TestStateSyncableVM{ + T: t, + }, + } + sender = engCfg.Sender.(*common.SenderTest) + ) + engCfg.VM = vm + + lastAcceptedBlk := &snowman.TestBlock{TestDecidable: choices.TestDecidable{ + IDV: ids.GenerateTestID(), + StatusV: choices.Accepted, + }} + + vm.LastAcceptedF = func(context.Context) (ids.ID, error) { + return lastAcceptedBlk.ID(), nil + } + + vm.GetBlockF = func(_ context.Context, blkID ids.ID) (snowman.Block, error) { + switch blkID { + case lastAcceptedBlk.ID(): + return lastAcceptedBlk, nil + default: + return nil, errUnknownBlock + } + } + + // add at least a peer to be reached out for blocks + vals := validators.NewManager() + engCfg.Validators = vals + vdr := ids.GenerateTestNodeID() + require.NoError(vals.AddStaker(engCfg.Ctx.SubnetID, vdr, nil, ids.Empty, 1)) + + // create the engine + te, err := newTransitive(engCfg) + require.NoError(err) + + // enable block backfilling and check blocks request starts with block provided by VM + reqBlk := ids.GenerateTestID() + vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, error) { + return reqBlk, nil + } + + var issuedBlkID ids.ID + sender.SendGetAncestorsF = func(ctx context.Context, ni ids.NodeID, u uint32, blkID ids.ID) { + issuedBlkID = blkID + } + + dummyCtx := context.Background() + reqNum := uint32(0) + require.NoError(te.Start(dummyCtx, uint32(reqNum))) + require.Equal(reqBlk, issuedBlkID) +} From 3e1838ac3f183efe57f0bbed492383c6db374261 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 30 Oct 2023 13:16:36 +0100 Subject: [PATCH 13/36] wip: block backfilling UTs --- snow/engine/snowman/transitive.go | 14 +- .../transitive_block_backfilling_test.go | 132 ++++++++++++++---- 2 files changed, 115 insertions(+), 31 deletions(-) diff --git a/snow/engine/snowman/transitive.go b/snow/engine/snowman/transitive.go index b9750fd6eddb..57d295ee74a6 100644 --- a/snow/engine/snowman/transitive.go +++ b/snow/engine/snowman/transitive.go @@ -5,6 +5,7 @@ package snowman import ( "context" + "errors" "fmt" "go.uber.org/zap" @@ -34,7 +35,11 @@ import ( const nonVerifiedCacheSize = 64 * units.MiB -var _ Engine = (*Transitive)(nil) +var ( + _ Engine = (*Transitive)(nil) + + errNoPeersToDownloadBlocksFrom = errors.New("no connected peers to download blocks from") +) func New(config Config) (Engine, error) { return newTransitive(config) @@ -1104,14 +1109,9 @@ func (t *Transitive) fetch(ctx context.Context, blkID ids.ID) error { return nil } - if _, err := t.VM.GetBlock(ctx, blkID); err == nil { - // Requesting known block is the stopping condition for block backfilling - return nil - } - validatorID, ok := t.fetchFrom.Peek() if !ok { - return fmt.Errorf("dropping request for %s as there are no peers", blkID) + return fmt.Errorf("dropping request for %s: %w", blkID, errNoPeersToDownloadBlocksFrom) } // We only allow one outbound request at a time from a node diff --git a/snow/engine/snowman/transitive_block_backfilling_test.go b/snow/engine/snowman/transitive_block_backfilling_test.go index a3f80061bef1..07e092a2d9c1 100644 --- a/snow/engine/snowman/transitive_block_backfilling_test.go +++ b/snow/engine/snowman/transitive_block_backfilling_test.go @@ -5,24 +5,123 @@ package snowman import ( "context" + "errors" "testing" + "github.com/stretchr/testify/require" + "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow/choices" "github.com/ava-labs/avalanchego/snow/consensus/snowman" "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/snow/engine/snowman/block" "github.com/ava-labs/avalanchego/snow/validators" - "github.com/stretchr/testify/require" ) +func TestGetAncestorsRequestIssuedIfBlockBackfillingIsEnabled(t *testing.T) { + require := require.New(t) + + engCfg, vm, sender, err := setupBlockBackfillingTests(t) + require.NoError(err) + + // create the engine + te, err := newTransitive(engCfg) + require.NoError(err) + + // enable block backfilling and check blocks request starts with block provided by VM + reqBlk := ids.GenerateTestID() + vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, error) { + return reqBlk, nil + } + + var issuedBlkID ids.ID + sender.SendGetAncestorsF = func(ctx context.Context, ni ids.NodeID, u uint32, blkID ids.ID) { + issuedBlkID = blkID + } + + dummyCtx := context.Background() + reqNum := uint32(0) + require.NoError(te.Start(dummyCtx, reqNum)) + require.Equal(reqBlk, issuedBlkID) +} + +func TestGetAncestorsRequestNotIssuedIfBlockBackfillingIsNotEnabled(t *testing.T) { + require := require.New(t) + + engCfg, vm, sender, err := setupBlockBackfillingTests(t) + require.NoError(err) + + // create the engine + te, err := newTransitive(engCfg) + require.NoError(err) + + // disable block backfilling + vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, error) { + return ids.Empty, block.ErrBlockBackfillingNotEnabled + } + + // this will make engine Start fail if SendGetAncestor is attempted + sender.CantSendGetAncestors = true + + dummyCtx := context.Background() + reqNum := uint32(0) + require.NoError(te.Start(dummyCtx, reqNum)) +} + +func TestEngineErrsIfBlockBackfillingIsEnabledCheckErrs(t *testing.T) { + require := require.New(t) + + engCfg, vm, _, err := setupBlockBackfillingTests(t) + require.NoError(err) + + // create the engine + te, err := newTransitive(engCfg) + require.NoError(err) + + // let BackfillBlocksEnabled err with non-flag error + customErr := errors.New("a custom error") + vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, error) { + return ids.Empty, customErr + } + + dummyCtx := context.Background() + reqNum := uint32(0) + err = te.Start(dummyCtx, reqNum) + require.ErrorIs(err, customErr) +} + +func TestEngineErrsIfThereAreNoPeersToDownloadBlocksFrom(t *testing.T) { + require := require.New(t) + + engCfg, vm, _, err := setupBlockBackfillingTests(t) + require.NoError(err) + + // drop validators, so that there are no peers connected to request blocks from + vals := validators.NewManager() + engCfg.Validators = vals + + // create the engine + te, err := newTransitive(engCfg) + require.NoError(err) + + // enable block backfilling + reqBlk := ids.GenerateTestID() + vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, error) { + return reqBlk, nil + } + + dummyCtx := context.Background() + reqNum := uint32(0) + err = te.Start(dummyCtx, reqNum) + require.ErrorIs(err, errNoPeersToDownloadBlocksFrom) +} + type fullVM struct { *block.TestVM *block.TestStateSyncableVM } -func TestGetAncestorsRequestIssuedIfStateSyncVMEnabledBlockBackfilling(t *testing.T) { - require := require.New(t) +func setupBlockBackfillingTests(t *testing.T) (Config, *fullVM, *common.SenderTest, error) { engCfg := DefaultConfigs() var ( @@ -36,9 +135,12 @@ func TestGetAncestorsRequestIssuedIfStateSyncVMEnabledBlockBackfilling(t *testin T: t, }, } - sender = engCfg.Sender.(*common.SenderTest) + sender = &common.SenderTest{ + T: t, + } ) engCfg.VM = vm + engCfg.Sender = sender lastAcceptedBlk := &snowman.TestBlock{TestDecidable: choices.TestDecidable{ IDV: ids.GenerateTestID(), @@ -62,25 +164,7 @@ func TestGetAncestorsRequestIssuedIfStateSyncVMEnabledBlockBackfilling(t *testin vals := validators.NewManager() engCfg.Validators = vals vdr := ids.GenerateTestNodeID() - require.NoError(vals.AddStaker(engCfg.Ctx.SubnetID, vdr, nil, ids.Empty, 1)) - - // create the engine - te, err := newTransitive(engCfg) - require.NoError(err) - - // enable block backfilling and check blocks request starts with block provided by VM - reqBlk := ids.GenerateTestID() - vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, error) { - return reqBlk, nil - } - - var issuedBlkID ids.ID - sender.SendGetAncestorsF = func(ctx context.Context, ni ids.NodeID, u uint32, blkID ids.ID) { - issuedBlkID = blkID - } + err := vals.AddStaker(engCfg.Ctx.SubnetID, vdr, nil, ids.Empty, 1) - dummyCtx := context.Background() - reqNum := uint32(0) - require.NoError(te.Start(dummyCtx, uint32(reqNum))) - require.Equal(reqBlk, issuedBlkID) + return engCfg, vm, sender, err } From 25f3e8de5faa9882d9ef0ac291ae367ea025f8e7 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 30 Oct 2023 14:30:41 +0100 Subject: [PATCH 14/36] wip: block backfilling UTs --- snow/engine/snowman/config_test.go | 4 +- snow/engine/snowman/transitive.go | 7 +- .../transitive_block_backfilling_test.go | 82 ++++++++++++++++++- 3 files changed, 83 insertions(+), 10 deletions(-) diff --git a/snow/engine/snowman/config_test.go b/snow/engine/snowman/config_test.go index f03b34259e04..325db778f056 100644 --- a/snow/engine/snowman/config_test.go +++ b/snow/engine/snowman/config_test.go @@ -31,6 +31,8 @@ func DefaultConfigs() Config { }, Consensus: &snowman.Topological{}, - Peers: commonCfg.StartupTracker, + Peers: commonCfg.StartupTracker, + AncestorsMaxContainersSent: 2000, + AncestorsMaxContainersReceived: 2000, } } diff --git a/snow/engine/snowman/transitive.go b/snow/engine/snowman/transitive.go index 57d295ee74a6..fdc0d5467a26 100644 --- a/snow/engine/snowman/transitive.go +++ b/snow/engine/snowman/transitive.go @@ -1074,7 +1074,7 @@ func (t *Transitive) Ancestors(ctx context.Context, nodeID ids.NodeID, requestID t.Ctx.Log.Info("block backfilling done") return nil case err != nil: - t.Ctx.Log.Debug("failed to parse blocks in Ancestors", + t.Ctx.Log.Debug("failed to backfill blocks in Ancestors", zap.Stringer("nodeID", nodeID), zap.Uint32("requestID", requestID), zap.Error(err), @@ -1104,11 +1104,6 @@ func (t *Transitive) GetAncestorsFailed(ctx context.Context, nodeID ids.NodeID, // Get block [blkID] and its ancestors from a peer func (t *Transitive) fetch(ctx context.Context, blkID ids.ID) error { - // Make sure we haven't already requested this block - if t.backfillingRequests.Contains(blkID) { - return nil - } - validatorID, ok := t.fetchFrom.Peek() if !ok { return fmt.Errorf("dropping request for %s: %w", blkID, errNoPeersToDownloadBlocksFrom) diff --git a/snow/engine/snowman/transitive_block_backfilling_test.go b/snow/engine/snowman/transitive_block_backfilling_test.go index 07e092a2d9c1..9dcd65b4fcc6 100644 --- a/snow/engine/snowman/transitive_block_backfilling_test.go +++ b/snow/engine/snowman/transitive_block_backfilling_test.go @@ -16,6 +16,7 @@ import ( "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/snow/engine/snowman/block" "github.com/ava-labs/avalanchego/snow/validators" + "github.com/ava-labs/avalanchego/utils/wrappers" ) func TestGetAncestorsRequestIssuedIfBlockBackfillingIsEnabled(t *testing.T) { @@ -116,6 +117,76 @@ func TestEngineErrsIfThereAreNoPeersToDownloadBlocksFrom(t *testing.T) { require.ErrorIs(err, errNoPeersToDownloadBlocksFrom) } +func TestAncestorsProcessing(t *testing.T) { + require := require.New(t) + + engCfg, vm, sender, err := setupBlockBackfillingTests(t) + require.NoError(err) + + // create the engine + te, err := newTransitive(engCfg) + require.NoError(err) + + // enable block backfilling + reqBlkFirst := ids.GenerateTestID() + vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, error) { + return reqBlkFirst, nil + } + issuedBlk := ids.Empty + sender.SendGetAncestorsF = func(ctx context.Context, ni ids.NodeID, u uint32, blkID ids.ID) { + issuedBlk = blkID + } + + // issue blocks request + dummyCtx := context.Background() + startReqNum := uint32(0) + require.NoError(te.Start(dummyCtx, startReqNum)) + + // process GetAncestor response + var ( + nodeID = engCfg.Validators.GetValidatorIDs(engCfg.Ctx.SubnetID)[0] + responseReqID = startReqNum + 1 + blkBytes = [][]byte{{1}, {2}, {3}} + pushedBlks [][]byte + reqBlkSecond = ids.GenerateTestID() + ) + vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, error) { + pushedBlks = b + return reqBlkSecond, nil + } + + { + // handle Ancestor response from unexpected nodeID + wrongNodeID := ids.GenerateTestNodeID() + require.NotEqual(nodeID, wrongNodeID) + require.NoError(te.Ancestors(dummyCtx, wrongNodeID, responseReqID, blkBytes)) + require.Nil(pushedBlks) // blocks from wrong NodeID are not pushed to VM + } + { + // handle Ancestor response with wrong requestID + wrongReqID := uint32(2023) + require.NotEqual(responseReqID, wrongReqID) + require.NoError(te.Ancestors(dummyCtx, nodeID, wrongReqID, blkBytes)) + require.Nil(pushedBlks) // blocks from wrong NodeID are not pushed to VM + } + { + // handle empty Ancestor response + emptyBlkBytes := [][]byte{} + require.NoError(te.Ancestors(dummyCtx, nodeID, responseReqID, emptyBlkBytes)) + require.Nil(pushedBlks) // blocks from wrong NodeID are not pushed to VM + require.Equal(reqBlkFirst, issuedBlk) // check that VM controls next block ID to be requested + } + { + // success + nodeID := engCfg.Validators.GetValidatorIDs(engCfg.Ctx.SubnetID)[1] + responseReqID++ // previous consumed by empty Ancestor response case + + require.NoError(te.Ancestors(dummyCtx, nodeID, responseReqID, blkBytes)) + require.Equal(blkBytes, pushedBlks) // blocks are pushed to VM + require.Equal(reqBlkSecond, issuedBlk) // check that VM controls next block ID to be requested + } +} + type fullVM struct { *block.TestVM *block.TestStateSyncableVM @@ -163,8 +234,13 @@ func setupBlockBackfillingTests(t *testing.T) (Config, *fullVM, *common.SenderTe // add at least a peer to be reached out for blocks vals := validators.NewManager() engCfg.Validators = vals - vdr := ids.GenerateTestNodeID() - err := vals.AddStaker(engCfg.Ctx.SubnetID, vdr, nil, ids.Empty, 1) + vdr1 := ids.GenerateTestNodeID() + vdr2 := ids.GenerateTestNodeID() + errs := wrappers.Errs{} + errs.Add( + vals.AddStaker(engCfg.Ctx.SubnetID, vdr1, nil, ids.Empty, 1), + vals.AddStaker(engCfg.Ctx.SubnetID, vdr2, nil, ids.Empty, 1), + ) - return engCfg, vm, sender, err + return engCfg, vm, sender, errs.Err } From 4664e268d67a89423f622afaa9c2199d6095d9e4 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 30 Oct 2023 15:27:07 +0100 Subject: [PATCH 15/36] wip: block backfilling UTs --- .../transitive_block_backfilling_test.go | 153 ++++++++++++++++++ 1 file changed, 153 insertions(+) diff --git a/snow/engine/snowman/transitive_block_backfilling_test.go b/snow/engine/snowman/transitive_block_backfilling_test.go index 9dcd65b4fcc6..49db94d3f1f7 100644 --- a/snow/engine/snowman/transitive_block_backfilling_test.go +++ b/snow/engine/snowman/transitive_block_backfilling_test.go @@ -187,6 +187,159 @@ func TestAncestorsProcessing(t *testing.T) { } } +func TestGetAncestorsFailedProcessing(t *testing.T) { + require := require.New(t) + + engCfg, vm, sender, err := setupBlockBackfillingTests(t) + require.NoError(err) + + // create the engine + te, err := newTransitive(engCfg) + require.NoError(err) + + // enable block backfilling + reqBlkFirst := ids.GenerateTestID() + vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, error) { + return reqBlkFirst, nil + } + issuedBlk := ids.Empty + sender.SendGetAncestorsF = func(ctx context.Context, ni ids.NodeID, u uint32, blkID ids.ID) { + issuedBlk = blkID + } + + // issue blocks request + dummyCtx := context.Background() + startReqNum := uint32(0) + require.NoError(te.Start(dummyCtx, startReqNum)) + + // process GetAncestor response + var ( + nodeID = engCfg.Validators.GetValidatorIDs(engCfg.Ctx.SubnetID)[0] + responseReqID = startReqNum + 1 + pushedBlks [][]byte + reqBlkSecond = ids.GenerateTestID() + ) + vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, error) { + pushedBlks = b + return reqBlkSecond, nil + } + { + // handle Ancestor response from unexpected nodeID + wrongNodeID := ids.GenerateTestNodeID() + require.NotEqual(nodeID, wrongNodeID) + require.NoError(te.GetAncestorsFailed(dummyCtx, wrongNodeID, responseReqID)) + require.Nil(pushedBlks) // blocks from wrong NodeID are not pushed to VM + } + { + // handle Ancestor response with wrong requestID + wrongReqID := uint32(2023) + require.NotEqual(responseReqID, wrongReqID) + require.NoError(te.GetAncestorsFailed(dummyCtx, nodeID, wrongReqID)) + require.Nil(pushedBlks) // blocks from wrong NodeID are not pushed to VM + } + { + // success + require.NoError(te.GetAncestorsFailed(dummyCtx, nodeID, responseReqID)) + require.Nil(pushedBlks) // no blocks are pushed to VM + require.Equal(reqBlkFirst, issuedBlk) // check that the same blk is requested again + } +} + +func TestBackfillingTerminatedByVM(t *testing.T) { + require := require.New(t) + + engCfg, vm, sender, err := setupBlockBackfillingTests(t) + require.NoError(err) + + // create the engine + te, err := newTransitive(engCfg) + require.NoError(err) + + // enable block backfilling + reqBlkFirst := ids.GenerateTestID() + vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, error) { + return reqBlkFirst, nil + } + + // start the engine + dummyCtx := context.Background() + responseReqID := uint32(0) + require.NoError(te.Start(dummyCtx, responseReqID)) + + // 1. Successfully request and download some blocks + { + var ( + nodeID = engCfg.Validators.GetValidatorIDs(engCfg.Ctx.SubnetID)[0] + responseReqID = responseReqID + 1 + blkBytes = [][]byte{{1}} // content does not matter here. We just need it non-empty + + pushedBlks = false + nextRequestedBlk = ids.GenerateTestID() + issuedBlk = ids.Empty + ) + + vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, error) { + pushedBlks = true + return nextRequestedBlk, nil // requestedBlkID does not really matter here + } + sender.SendGetAncestorsF = func(ctx context.Context, ni ids.NodeID, u uint32, blkID ids.ID) { + issuedBlk = blkID + } + require.NoError(te.Ancestors(dummyCtx, nodeID, responseReqID, blkBytes)) + require.True(pushedBlks) + require.Equal(nextRequestedBlk, issuedBlk) + } + + // 2. Successfully request and download some more blocks + { + var ( + nodeID = engCfg.Validators.GetValidatorIDs(engCfg.Ctx.SubnetID)[0] + responseReqID = responseReqID + 2 + blkBytes = [][]byte{{1}} // content does not matter here. We just need it non-empty + + pushedBlks = false + nextRequestedBlk = ids.GenerateTestID() + issuedBlk = ids.Empty + ) + + vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, error) { + pushedBlks = true + return nextRequestedBlk, nil // requestedBlkID does not really matter here + } + sender.SendGetAncestorsF = func(ctx context.Context, ni ids.NodeID, u uint32, blkID ids.ID) { + issuedBlk = blkID + } + + require.NoError(te.Ancestors(dummyCtx, nodeID, responseReqID, blkBytes)) + require.True(pushedBlks) + require.Equal(nextRequestedBlk, issuedBlk) + } + + // 3. Let the VM stop block downloading (block backfilling complete) + { + var ( + nodeID = engCfg.Validators.GetValidatorIDs(engCfg.Ctx.SubnetID)[0] + responseReqID = responseReqID + 3 + blkBytes = [][]byte{{1}} // content does not matter here. We just need it non-empty + + pushedBlks = false + issuedBlkRequest = false + ) + + vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, error) { + pushedBlks = true + return ids.Empty, block.ErrStopBlockBackfilling + } + sender.SendGetAncestorsF = func(ctx context.Context, ni ids.NodeID, u uint32, blkID ids.ID) { + issuedBlkRequest = true + } + + require.NoError(te.Ancestors(dummyCtx, nodeID, responseReqID, blkBytes)) + require.True(pushedBlks) + require.False(issuedBlkRequest) + } +} + type fullVM struct { *block.TestVM *block.TestStateSyncableVM From f6c55462c1706956e6d686d1fdf101f47239e6cd Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 30 Oct 2023 20:16:21 +0100 Subject: [PATCH 16/36] fixed blocks backfilling restart --- snow/engine/snowman/transitive.go | 27 +++-- .../transitive_block_backfilling_test.go | 100 ++++++++++++------ 2 files changed, 86 insertions(+), 41 deletions(-) diff --git a/snow/engine/snowman/transitive.go b/snow/engine/snowman/transitive.go index fdc0d5467a26..88611450da7c 100644 --- a/snow/engine/snowman/transitive.go +++ b/snow/engine/snowman/transitive.go @@ -98,9 +98,10 @@ type Transitive struct { errs wrappers.Errs // START OF BLOCK BACKFILLING STUFF - fetchFrom set.Set[ids.NodeID] // picked from bootstrapper - peers tracker.Peers - backfillingRequests common.Requests // tracks which validators were asked for which containers in which requests + fetchFrom set.Set[ids.NodeID] // picked from bootstrapper + peers tracker.Peers + backfillingRequests common.Requests // tracks which validators were asked for which block in which requests + blkBackfillingInterrupted bool // flag to allow backfilling restart after recovering from validators disconnections // END OF BLOCK BACKFILLING STUFF } @@ -145,8 +146,9 @@ func newTransitive(config Config) (*Transitive, error) { ), // block-backfilling stuff - fetchFrom: set.Of[ids.NodeID](config.Validators.GetValidatorIDs(config.Ctx.SubnetID)...), - peers: config.Peers, + fetchFrom: set.Of[ids.NodeID](config.Validators.GetValidatorIDs(config.Ctx.SubnetID)...), + peers: config.Peers, + blkBackfillingInterrupted: len(config.Peers.PreferredPeers()) > 0, } return t, t.metrics.Initialize("", config.Ctx.Registerer) @@ -1132,10 +1134,23 @@ func (t *Transitive) Connected(ctx context.Context, nodeID ids.NodeID, nodeVersi if _, ok := t.Validators.GetValidator(t.Ctx.SubnetID, nodeID); ok { t.fetchFrom.Add(nodeID) } - return t.VM.Connected(ctx, nodeID, nodeVersion) + if err := t.VM.Connected(ctx, nodeID, nodeVersion); err != nil { + return err + } + + if !t.blkBackfillingInterrupted { + return nil + } + + // first validator reconnected. Resume blocks backfilling if needed + t.blkBackfillingInterrupted = false + return t.startBlockBackfilling(ctx) } func (t *Transitive) Disconnected(ctx context.Context, nodeID ids.NodeID) error { t.markUnavailable(nodeID) + + // if there is no validator left, flag that blocks backfilling is interrupted. + t.blkBackfillingInterrupted = len(t.fetchFrom) == 0 return t.VM.Disconnected(ctx, nodeID) } diff --git a/snow/engine/snowman/transitive_block_backfilling_test.go b/snow/engine/snowman/transitive_block_backfilling_test.go index 49db94d3f1f7..21a4161455b6 100644 --- a/snow/engine/snowman/transitive_block_backfilling_test.go +++ b/snow/engine/snowman/transitive_block_backfilling_test.go @@ -17,6 +17,7 @@ import ( "github.com/ava-labs/avalanchego/snow/engine/snowman/block" "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils/wrappers" + "github.com/ava-labs/avalanchego/version" ) func TestGetAncestorsRequestIssuedIfBlockBackfillingIsEnabled(t *testing.T) { @@ -94,13 +95,9 @@ func TestEngineErrsIfBlockBackfillingIsEnabledCheckErrs(t *testing.T) { func TestEngineErrsIfThereAreNoPeersToDownloadBlocksFrom(t *testing.T) { require := require.New(t) - engCfg, vm, _, err := setupBlockBackfillingTests(t) + engCfg, vm, sender, err := setupBlockBackfillingTests(t) require.NoError(err) - // drop validators, so that there are no peers connected to request blocks from - vals := validators.NewManager() - engCfg.Validators = vals - // create the engine te, err := newTransitive(engCfg) require.NoError(err) @@ -111,10 +108,33 @@ func TestEngineErrsIfThereAreNoPeersToDownloadBlocksFrom(t *testing.T) { return reqBlk, nil } + var ( + issuedBlkRequest = false + issuedBlkID ids.ID + ) + sender.SendGetAncestorsF = func(ctx context.Context, ni ids.NodeID, u uint32, blkID ids.ID) { + issuedBlkRequest = true + issuedBlkID = blkID + } + + // disconnect all validators, so that there are no peers to download blocks from dummyCtx := context.Background() + for _, valID := range engCfg.Validators.GetValidatorIDs(engCfg.Ctx.SubnetID) { + require.NoError(te.Disconnected(dummyCtx, valID)) + } + reqNum := uint32(0) err = te.Start(dummyCtx, reqNum) require.ErrorIs(err, errNoPeersToDownloadBlocksFrom) + + // riconnect at least a validator and show that GetAncestors requests are issued + for _, valID := range engCfg.Validators.GetValidatorIDs(engCfg.Ctx.SubnetID) { + require.NoError(te.Connected(dummyCtx, valID, version.CurrentApp)) + } + + // check that GetAncestors request is issued once a validator has reconnected + require.True(issuedBlkRequest) + require.Equal(reqBlk, issuedBlkID) } func TestAncestorsProcessing(t *testing.T) { @@ -263,21 +283,22 @@ func TestBackfillingTerminatedByVM(t *testing.T) { // start the engine dummyCtx := context.Background() - responseReqID := uint32(0) - require.NoError(te.Start(dummyCtx, responseReqID)) + startReqNum := uint32(0) + require.NoError(te.Start(dummyCtx, startReqNum)) - // 1. Successfully request and download some blocks - { - var ( - nodeID = engCfg.Validators.GetValidatorIDs(engCfg.Ctx.SubnetID)[0] - responseReqID = responseReqID + 1 - blkBytes = [][]byte{{1}} // content does not matter here. We just need it non-empty + var ( + nodeID = engCfg.Validators.GetValidatorIDs(engCfg.Ctx.SubnetID)[0] + responseReqID = startReqNum + blkBytes = [][]byte{{1}} // content does not matter here. We just need it non-empty - pushedBlks = false - nextRequestedBlk = ids.GenerateTestID() - issuedBlk = ids.Empty - ) + pushedBlks = false + nextRequestedBlk = ids.GenerateTestID() + issuedBlk = ids.Empty + ) + // 1. Successfully request and download some blocks + { + responseReqID++ vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, error) { pushedBlks = true return nextRequestedBlk, nil // requestedBlkID does not really matter here @@ -292,15 +313,10 @@ func TestBackfillingTerminatedByVM(t *testing.T) { // 2. Successfully request and download some more blocks { - var ( - nodeID = engCfg.Validators.GetValidatorIDs(engCfg.Ctx.SubnetID)[0] - responseReqID = responseReqID + 2 - blkBytes = [][]byte{{1}} // content does not matter here. We just need it non-empty - - pushedBlks = false - nextRequestedBlk = ids.GenerateTestID() - issuedBlk = ids.Empty - ) + pushedBlks = false + nextRequestedBlk = ids.GenerateTestID() + issuedBlk = ids.Empty + responseReqID++ vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, error) { pushedBlks = true @@ -315,16 +331,30 @@ func TestBackfillingTerminatedByVM(t *testing.T) { require.Equal(nextRequestedBlk, issuedBlk) } - // 3. Let the VM stop block downloading (block backfilling complete) + // 3. If block backfilling fails in VM, the same blocks are requested to a different VM { - var ( - nodeID = engCfg.Validators.GetValidatorIDs(engCfg.Ctx.SubnetID)[0] - responseReqID = responseReqID + 3 - blkBytes = [][]byte{{1}} // content does not matter here. We just need it non-empty + pushedBlks = false + issuedBlk = ids.Empty + responseReqID++ - pushedBlks = false - issuedBlkRequest = false - ) + vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, error) { + pushedBlks = true + return ids.Empty, errors.New("custom error upon backfilling") + } + sender.SendGetAncestorsF = func(ctx context.Context, ni ids.NodeID, u uint32, blkID ids.ID) { + issuedBlk = blkID + } + + require.NoError(te.Ancestors(dummyCtx, nodeID, responseReqID, blkBytes)) + require.True(pushedBlks) + require.Equal(nextRequestedBlk, issuedBlk) // we expect to ask again block requested at step 2 + } + + // 4. Let the VM stop block downloading (block backfilling complete) + { + issuedBlkRequest := false + pushedBlks = false + responseReqID++ vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, error) { pushedBlks = true @@ -336,7 +366,7 @@ func TestBackfillingTerminatedByVM(t *testing.T) { require.NoError(te.Ancestors(dummyCtx, nodeID, responseReqID, blkBytes)) require.True(pushedBlks) - require.False(issuedBlkRequest) + require.False(issuedBlkRequest) // no more requests, block backfilling done } } From 46481ab82e1eae5c36b5712696d59a1c5d3962a2 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 30 Oct 2023 20:53:42 +0100 Subject: [PATCH 17/36] fixed blocks backfilling UTs flakiness --- .../transitive_block_backfilling_test.go | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/snow/engine/snowman/transitive_block_backfilling_test.go b/snow/engine/snowman/transitive_block_backfilling_test.go index 21a4161455b6..85e19786565c 100644 --- a/snow/engine/snowman/transitive_block_backfilling_test.go +++ b/snow/engine/snowman/transitive_block_backfilling_test.go @@ -147,6 +147,10 @@ func TestAncestorsProcessing(t *testing.T) { te, err := newTransitive(engCfg) require.NoError(err) + // for current test we need a single validator. Disconnect the other + dummyCtx := context.Background() + require.NoError(te.Disconnected(dummyCtx, engCfg.Validators.GetValidatorIDs(engCfg.Ctx.SubnetID)[1])) + // enable block backfilling reqBlkFirst := ids.GenerateTestID() vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, error) { @@ -158,7 +162,6 @@ func TestAncestorsProcessing(t *testing.T) { } // issue blocks request - dummyCtx := context.Background() startReqNum := uint32(0) require.NoError(te.Start(dummyCtx, startReqNum)) @@ -191,6 +194,10 @@ func TestAncestorsProcessing(t *testing.T) { } { // handle empty Ancestor response + + // Connect second validator, to allow requesting it the block following faulty response from first validator + require.NoError(te.Connected(dummyCtx, engCfg.Validators.GetValidatorIDs(engCfg.Ctx.SubnetID)[1], version.CurrentApp)) + emptyBlkBytes := [][]byte{} require.NoError(te.Ancestors(dummyCtx, nodeID, responseReqID, emptyBlkBytes)) require.Nil(pushedBlks) // blocks from wrong NodeID are not pushed to VM @@ -275,6 +282,10 @@ func TestBackfillingTerminatedByVM(t *testing.T) { te, err := newTransitive(engCfg) require.NoError(err) + // for current test we need a single validator. Disconnect the other + dummyCtx := context.Background() + require.NoError(te.Disconnected(dummyCtx, engCfg.Validators.GetValidatorIDs(engCfg.Ctx.SubnetID)[1])) + // enable block backfilling reqBlkFirst := ids.GenerateTestID() vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, error) { @@ -282,7 +293,6 @@ func TestBackfillingTerminatedByVM(t *testing.T) { } // start the engine - dummyCtx := context.Background() startReqNum := uint32(0) require.NoError(te.Start(dummyCtx, startReqNum)) @@ -417,8 +427,8 @@ func setupBlockBackfillingTests(t *testing.T) (Config, *fullVM, *common.SenderTe // add at least a peer to be reached out for blocks vals := validators.NewManager() engCfg.Validators = vals - vdr1 := ids.GenerateTestNodeID() - vdr2 := ids.GenerateTestNodeID() + vdr1 := ids.NodeID{1} + vdr2 := ids.NodeID{2} errs := wrappers.Errs{} errs.Add( vals.AddStaker(engCfg.Ctx.SubnetID, vdr1, nil, ids.Empty, 1), From 4eb0ccbd32706531b2948b925102ccfe3ccf6bcd Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 30 Oct 2023 21:54:54 +0100 Subject: [PATCH 18/36] repackaged block backfilling into ad-hoc struct --- .../snowman/syncer/blocks_backfiller.go | 196 ++++++++++++++++++ snow/engine/snowman/transitive.go | 180 ++-------------- .../transitive_block_backfilling_test.go | 3 +- 3 files changed, 220 insertions(+), 159 deletions(-) create mode 100644 snow/engine/snowman/syncer/blocks_backfiller.go diff --git a/snow/engine/snowman/syncer/blocks_backfiller.go b/snow/engine/snowman/syncer/blocks_backfiller.go new file mode 100644 index 000000000000..c4394fa9f824 --- /dev/null +++ b/snow/engine/snowman/syncer/blocks_backfiller.go @@ -0,0 +1,196 @@ +// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package syncer + +import ( + "context" + "errors" + "fmt" + + "go.uber.org/zap" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/snow" + "github.com/ava-labs/avalanchego/snow/engine/common" + "github.com/ava-labs/avalanchego/snow/engine/common/tracker" + "github.com/ava-labs/avalanchego/snow/engine/snowman/block" + "github.com/ava-labs/avalanchego/snow/validators" + "github.com/ava-labs/avalanchego/utils/set" +) + +var ( + _ common.AncestorsHandler = (*BlockBackfiller)(nil) + + ErrNoPeersToDownloadBlocksFrom = errors.New("no connected peers to download blocks from") +) + +type BlockBackfillerConfig struct { + Ctx *snow.ConsensusContext + VM block.ChainVM + Sender common.Sender + Validators validators.Manager + Peers tracker.Peers + AncestorsMaxContainersSent int + AncestorsMaxContainersReceived int + + SharedRequestID *uint32 +} + +type BlockBackfiller struct { + BlockBackfillerConfig + + fetchFrom set.Set[ids.NodeID] // picked from bootstrapper + outstandingRequests common.Requests // tracks which validators were asked for which block in which requests + interrupted bool // flag to allow backfilling restart after recovering from validators disconnections +} + +func NewBlockBackfiller(cfg BlockBackfillerConfig) *BlockBackfiller { + return &BlockBackfiller{ + BlockBackfillerConfig: cfg, + + fetchFrom: set.Of[ids.NodeID](cfg.Validators.GetValidatorIDs(cfg.Ctx.SubnetID)...), + interrupted: len(cfg.Peers.PreferredPeers()) > 0, + } +} + +func (bb *BlockBackfiller) Start(ctx context.Context) error { + ssVM, ok := bb.VM.(block.StateSyncableVM) + if !ok { + return nil // nothing to do + } + + switch wantedBlk, err := ssVM.BackfillBlocksEnabled(ctx); { + case err == block.ErrBlockBackfillingNotEnabled: + bb.Ctx.Log.Info("block backfilling not enabled") + return nil + case err != nil: + return fmt.Errorf("failed checking if state sync block backfilling is enabled: %w", err) + default: + return bb.fetch(ctx, wantedBlk) + } +} + +// Ancestors handles the receipt of multiple containers. Should be received in +// response to a GetAncestors message to [nodeID] with request ID [requestID] +func (bb *BlockBackfiller) Ancestors(ctx context.Context, nodeID ids.NodeID, requestID uint32, blks [][]byte) error { + // Make sure this is in response to a request we made + wantedBlkID, ok := bb.outstandingRequests.Remove(nodeID, requestID) + if !ok { // this message isn't in response to a request we made + bb.Ctx.Log.Debug("received unexpected Ancestors", + zap.Stringer("nodeID", nodeID), + zap.Uint32("requestID", requestID), + ) + return nil + } + + lenBlks := len(blks) + if lenBlks == 0 { + bb.Ctx.Log.Debug("received Ancestors with no block", + zap.Stringer("nodeID", nodeID), + zap.Uint32("requestID", requestID), + ) + + bb.markUnavailable(nodeID) + + // Send another request for this + return bb.fetch(ctx, wantedBlkID) + } + + // This node has responded - so add it back into the set + bb.fetchFrom.Add(nodeID) + + if lenBlks > bb.AncestorsMaxContainersReceived { + blks = blks[:bb.AncestorsMaxContainersReceived] + bb.Ctx.Log.Debug("ignoring containers in Ancestors", + zap.Int("numContainers", lenBlks-bb.AncestorsMaxContainersReceived), + zap.Stringer("nodeID", nodeID), + zap.Uint32("requestID", requestID), + ) + } + + ssVM, ok := bb.VM.(block.StateSyncableVM) + if !ok { + return nil // nothing to do + } + + switch nextWantedBlkID, err := ssVM.BackfillBlocks(ctx, blks); { + case err == block.ErrStopBlockBackfilling: + bb.Ctx.Log.Info("block backfilling done") + return nil + case err != nil: + bb.Ctx.Log.Debug("failed to backfill blocks in Ancestors", + zap.Stringer("nodeID", nodeID), + zap.Uint32("requestID", requestID), + zap.Error(err), + ) + return bb.fetch(ctx, wantedBlkID) + default: + return bb.fetch(ctx, nextWantedBlkID) + } +} + +func (bb *BlockBackfiller) GetAncestorsFailed(ctx context.Context, nodeID ids.NodeID, requestID uint32) error { + blkID, ok := bb.outstandingRequests.Remove(nodeID, requestID) + if !ok { + bb.Ctx.Log.Debug("unexpectedly called GetAncestorsFailed", + zap.Stringer("nodeID", nodeID), + zap.Uint32("requestID", requestID), + ) + return nil + } + + // This node timed out their request, so we can add them back to [fetchFrom] + bb.fetchFrom.Add(nodeID) + + // Send another request for this + return bb.fetch(ctx, blkID) +} + +// Get block [blkID] and its ancestors from a peer +func (bb *BlockBackfiller) fetch(ctx context.Context, blkID ids.ID) error { + validatorID, ok := bb.fetchFrom.Peek() + if !ok { + return fmt.Errorf("dropping request for %s: %w", blkID, ErrNoPeersToDownloadBlocksFrom) + } + + // We only allow one outbound request at a time from a node + bb.markUnavailable(validatorID) + *bb.SharedRequestID++ + bb.outstandingRequests.Add(validatorID, *bb.SharedRequestID, blkID) + bb.Sender.SendGetAncestors(ctx, validatorID, *bb.SharedRequestID, blkID) + return nil +} + +func (bb *BlockBackfiller) markUnavailable(nodeID ids.NodeID) { + bb.fetchFrom.Remove(nodeID) + + // if [fetchFrom] has become empty, reset it to the currently preferred + // peers + if bb.fetchFrom.Len() == 0 { + bb.fetchFrom = bb.Peers.PreferredPeers() + } +} + +func (bb *BlockBackfiller) Connected(ctx context.Context, nodeID ids.NodeID) error { + // Ensure fetchFrom reflects proper validator list + if _, ok := bb.Validators.GetValidator(bb.Ctx.SubnetID, nodeID); ok { + bb.fetchFrom.Add(nodeID) + } + + if !bb.interrupted { + return nil + } + + // first validator reconnected. Resume blocks backfilling if needed + bb.interrupted = false + return bb.Start(ctx) +} + +func (bb *BlockBackfiller) Disconnected(nodeID ids.NodeID) error { + bb.markUnavailable(nodeID) + + // if there is no validator left, flag that blocks backfilling is interrupted. + bb.interrupted = len(bb.fetchFrom) == 0 + return nil +} diff --git a/snow/engine/snowman/transitive.go b/snow/engine/snowman/transitive.go index 88611450da7c..47a5afbafefe 100644 --- a/snow/engine/snowman/transitive.go +++ b/snow/engine/snowman/transitive.go @@ -5,7 +5,6 @@ package snowman import ( "context" - "errors" "fmt" "go.uber.org/zap" @@ -21,7 +20,7 @@ import ( "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/snow/engine/common/tracker" "github.com/ava-labs/avalanchego/snow/engine/snowman/ancestor" - "github.com/ava-labs/avalanchego/snow/engine/snowman/block" + "github.com/ava-labs/avalanchego/snow/engine/snowman/syncer" "github.com/ava-labs/avalanchego/snow/event" "github.com/ava-labs/avalanchego/utils/bag" "github.com/ava-labs/avalanchego/utils/constants" @@ -35,11 +34,7 @@ import ( const nonVerifiedCacheSize = 64 * units.MiB -var ( - _ Engine = (*Transitive)(nil) - - errNoPeersToDownloadBlocksFrom = errors.New("no connected peers to download blocks from") -) +var _ Engine = (*Transitive)(nil) func New(config Config) (Engine, error) { return newTransitive(config) @@ -62,6 +57,8 @@ type Transitive struct { common.AcceptedHandler common.AppHandler + *syncer.BlockBackfiller + RequestID uint32 // track outstanding preference requests @@ -96,13 +93,6 @@ type Transitive struct { // errs tracks if an error has occurred in a callback errs wrappers.Errs - - // START OF BLOCK BACKFILLING STUFF - fetchFrom set.Set[ids.NodeID] // picked from bootstrapper - peers tracker.Peers - backfillingRequests common.Requests // tracks which validators were asked for which block in which requests - blkBackfillingInterrupted bool // flag to allow backfilling restart after recovering from validators disconnections - // END OF BLOCK BACKFILLING STUFF } func newTransitive(config Config) (*Transitive, error) { @@ -144,12 +134,19 @@ func newTransitive(config Config) (*Transitive, error) { "", config.Ctx.Registerer, ), - - // block-backfilling stuff - fetchFrom: set.Of[ids.NodeID](config.Validators.GetValidatorIDs(config.Ctx.SubnetID)...), - peers: config.Peers, - blkBackfillingInterrupted: len(config.Peers.PreferredPeers()) > 0, } + t.BlockBackfiller = syncer.NewBlockBackfiller( + syncer.BlockBackfillerConfig{ + Ctx: config.Ctx, + VM: config.VM, + Sender: config.Sender, + Validators: config.Validators, + Peers: config.Peers, + AncestorsMaxContainersSent: config.AncestorsMaxContainersSent, + AncestorsMaxContainersReceived: config.AncestorsMaxContainersReceived, + SharedRequestID: &t.RequestID, + }, + ) return t, t.metrics.Initialize("", config.Ctx.Registerer) } @@ -469,9 +466,7 @@ func (t *Transitive) Start(ctx context.Context, startReqID uint32) error { } // Start Block backfilling if needed - // TODO: for now we extend transitive engine with backfilling features - // Later on we'll repackage them into a separate struct to be moved in syncer package. - return t.startBlockBackfilling(ctx) + return t.BlockBackfiller.Start(ctx) } func (t *Transitive) HealthCheck(ctx context.Context) (interface{}, error) { @@ -1010,147 +1005,16 @@ func (t *Transitive) addUnverifiedBlockToConsensus(ctx context.Context, blk snow }) } -// BLOCK BACKFILLING STUFF -func (t *Transitive) startBlockBackfilling(ctx context.Context) error { - ssVM, ok := t.VM.(block.StateSyncableVM) - if !ok { - return nil // nothing to do - } - - switch wantedBlk, err := ssVM.BackfillBlocksEnabled(ctx); { - case err == block.ErrBlockBackfillingNotEnabled: - t.Ctx.Log.Info("block backfilling not enabled") - return nil - case err != nil: - return fmt.Errorf("failed checking if state sync block backfilling is enabled: %w", err) - default: - return t.fetch(ctx, wantedBlk) - } -} - -// Ancestors handles the receipt of multiple containers. Should be received in -// response to a GetAncestors message to [nodeID] with request ID [requestID] -func (t *Transitive) Ancestors(ctx context.Context, nodeID ids.NodeID, requestID uint32, blks [][]byte) error { - // Make sure this is in response to a request we made - wantedBlkID, ok := t.backfillingRequests.Remove(nodeID, requestID) - if !ok { // this message isn't in response to a request we made - t.Ctx.Log.Debug("received unexpected Ancestors", - zap.Stringer("nodeID", nodeID), - zap.Uint32("requestID", requestID), - ) - return nil - } - - lenBlks := len(blks) - if lenBlks == 0 { - t.Ctx.Log.Debug("received Ancestors with no block", - zap.Stringer("nodeID", nodeID), - zap.Uint32("requestID", requestID), - ) - - t.markUnavailable(nodeID) - - // Send another request for this - return t.fetch(ctx, wantedBlkID) - } - - // This node has responded - so add it back into the set - t.fetchFrom.Add(nodeID) - - if lenBlks > t.Config.AncestorsMaxContainersReceived { - blks = blks[:t.Config.AncestorsMaxContainersReceived] - t.Ctx.Log.Debug("ignoring containers in Ancestors", - zap.Int("numContainers", lenBlks-t.Config.AncestorsMaxContainersReceived), - zap.Stringer("nodeID", nodeID), - zap.Uint32("requestID", requestID), - ) - } - - ssVM, ok := t.VM.(block.StateSyncableVM) - if !ok { - return nil // nothing to do - } - - switch nextWantedBlkID, err := ssVM.BackfillBlocks(ctx, blks); { - case err == block.ErrStopBlockBackfilling: - t.Ctx.Log.Info("block backfilling done") - return nil - case err != nil: - t.Ctx.Log.Debug("failed to backfill blocks in Ancestors", - zap.Stringer("nodeID", nodeID), - zap.Uint32("requestID", requestID), - zap.Error(err), - ) - return t.fetch(ctx, wantedBlkID) - default: - return t.fetch(ctx, nextWantedBlkID) - } -} - -func (t *Transitive) GetAncestorsFailed(ctx context.Context, nodeID ids.NodeID, requestID uint32) error { - blkID, ok := t.backfillingRequests.Remove(nodeID, requestID) - if !ok { - t.Ctx.Log.Debug("unexpectedly called GetAncestorsFailed", - zap.Stringer("nodeID", nodeID), - zap.Uint32("requestID", requestID), - ) - return nil - } - - // This node timed out their request, so we can add them back to [fetchFrom] - t.fetchFrom.Add(nodeID) - - // Send another request for this - return t.fetch(ctx, blkID) -} - -// Get block [blkID] and its ancestors from a peer -func (t *Transitive) fetch(ctx context.Context, blkID ids.ID) error { - validatorID, ok := t.fetchFrom.Peek() - if !ok { - return fmt.Errorf("dropping request for %s: %w", blkID, errNoPeersToDownloadBlocksFrom) - } - - // We only allow one outbound request at a time from a node - t.markUnavailable(validatorID) - t.RequestID++ - t.backfillingRequests.Add(validatorID, t.RequestID, blkID) - t.Sender.SendGetAncestors(ctx, validatorID, t.RequestID, blkID) - return nil -} - -func (t *Transitive) markUnavailable(nodeID ids.NodeID) { - t.fetchFrom.Remove(nodeID) - - // if [fetchFrom] has become empty, reset it to the currently preferred - // peers - if t.fetchFrom.Len() == 0 { - t.fetchFrom = t.peers.PreferredPeers() - } -} - func (t *Transitive) Connected(ctx context.Context, nodeID ids.NodeID, nodeVersion *version.Application) error { - // Ensure fetchFrom reflects proper validator list - if _, ok := t.Validators.GetValidator(t.Ctx.SubnetID, nodeID); ok { - t.fetchFrom.Add(nodeID) - } if err := t.VM.Connected(ctx, nodeID, nodeVersion); err != nil { return err } - - if !t.blkBackfillingInterrupted { - return nil - } - - // first validator reconnected. Resume blocks backfilling if needed - t.blkBackfillingInterrupted = false - return t.startBlockBackfilling(ctx) + return t.BlockBackfiller.Connected(ctx, nodeID) } func (t *Transitive) Disconnected(ctx context.Context, nodeID ids.NodeID) error { - t.markUnavailable(nodeID) - - // if there is no validator left, flag that blocks backfilling is interrupted. - t.blkBackfillingInterrupted = len(t.fetchFrom) == 0 - return t.VM.Disconnected(ctx, nodeID) + if err := t.VM.Disconnected(ctx, nodeID); err != nil { + return err + } + return t.BlockBackfiller.Disconnected(nodeID) } diff --git a/snow/engine/snowman/transitive_block_backfilling_test.go b/snow/engine/snowman/transitive_block_backfilling_test.go index 85e19786565c..08d69f2ddbde 100644 --- a/snow/engine/snowman/transitive_block_backfilling_test.go +++ b/snow/engine/snowman/transitive_block_backfilling_test.go @@ -15,6 +15,7 @@ import ( "github.com/ava-labs/avalanchego/snow/consensus/snowman" "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/snow/engine/snowman/block" + "github.com/ava-labs/avalanchego/snow/engine/snowman/syncer" "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/avalanchego/version" @@ -125,7 +126,7 @@ func TestEngineErrsIfThereAreNoPeersToDownloadBlocksFrom(t *testing.T) { reqNum := uint32(0) err = te.Start(dummyCtx, reqNum) - require.ErrorIs(err, errNoPeersToDownloadBlocksFrom) + require.ErrorIs(err, syncer.ErrNoPeersToDownloadBlocksFrom) // riconnect at least a validator and show that GetAncestors requests are issued for _, valID := range engCfg.Validators.GetValidatorIDs(engCfg.Ctx.SubnetID) { From bdaa39d4c356c3d404ecb8e19a52d5000804b521 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 30 Oct 2023 22:34:07 +0100 Subject: [PATCH 19/36] fixed state sync termination --- snow/engine/snowman/bootstrap/bootstrapper.go | 2 -- snow/engine/snowman/syncer/blocks_backfiller.go | 6 ++++++ snow/engine/snowman/transitive.go | 3 +-- vms/platformvm/vm_test.go | 7 ++++++- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index f6725aa00ba5..04afbb140d6b 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -309,8 +309,6 @@ func (b *bootstrapper) Notify(_ context.Context, msg common.Message) error { ) return nil } - - b.Ctx.StateSyncing.Set(false) return nil } diff --git a/snow/engine/snowman/syncer/blocks_backfiller.go b/snow/engine/snowman/syncer/blocks_backfiller.go index c4394fa9f824..60a0150063a7 100644 --- a/snow/engine/snowman/syncer/blocks_backfiller.go +++ b/snow/engine/snowman/syncer/blocks_backfiller.go @@ -34,6 +34,9 @@ type BlockBackfillerConfig struct { AncestorsMaxContainersSent int AncestorsMaxContainersReceived int + // BlockBackfiller is supposed to be embedded into the engine. + // So requestID is shared among BlockBackfiller and the engine to + // avoid duplications. SharedRequestID *uint32 } @@ -57,12 +60,14 @@ func NewBlockBackfiller(cfg BlockBackfillerConfig) *BlockBackfiller { func (bb *BlockBackfiller) Start(ctx context.Context) error { ssVM, ok := bb.VM.(block.StateSyncableVM) if !ok { + bb.Ctx.StateSyncing.Set(false) return nil // nothing to do } switch wantedBlk, err := ssVM.BackfillBlocksEnabled(ctx); { case err == block.ErrBlockBackfillingNotEnabled: bb.Ctx.Log.Info("block backfilling not enabled") + bb.Ctx.StateSyncing.Set(false) return nil case err != nil: return fmt.Errorf("failed checking if state sync block backfilling is enabled: %w", err) @@ -117,6 +122,7 @@ func (bb *BlockBackfiller) Ancestors(ctx context.Context, nodeID ids.NodeID, req switch nextWantedBlkID, err := ssVM.BackfillBlocks(ctx, blks); { case err == block.ErrStopBlockBackfilling: bb.Ctx.Log.Info("block backfilling done") + bb.Ctx.StateSyncing.Set(false) return nil case err != nil: bb.Ctx.Log.Debug("failed to backfill blocks in Ancestors", diff --git a/snow/engine/snowman/transitive.go b/snow/engine/snowman/transitive.go index 47a5afbafefe..cb2940e1c295 100644 --- a/snow/engine/snowman/transitive.go +++ b/snow/engine/snowman/transitive.go @@ -392,8 +392,7 @@ func (t *Transitive) Notify(ctx context.Context, msg common.Message) error { t.pendingBuildBlocks++ return t.buildBlocks(ctx) case common.StateSyncDone: - t.Ctx.StateSyncing.Set(false) - return nil + return t.BlockBackfiller.Start(ctx) default: t.Ctx.Log.Warn("received an unexpected message from the VM", zap.Stringer("messageString", msg), diff --git a/vms/platformvm/vm_test.go b/vms/platformvm/vm_test.go index 2db4146d05df..f82d32a7227d 100644 --- a/vms/platformvm/vm_test.go +++ b/vms/platformvm/vm_test.go @@ -1519,6 +1519,7 @@ func TestBootstrapPartiallyAccepted(t *testing.T) { ) require.NoError(err) + peers = tracker.NewPeers() h, err := handler.New( bootstrapConfig.Ctx, beacons, @@ -1528,7 +1529,7 @@ func TestBootstrapPartiallyAccepted(t *testing.T) { cpuTracker, vm, subnets.New(ctx.NodeID, subnets.Config{}), - tracker.NewPeers(), + peers, ) require.NoError(err) @@ -1550,6 +1551,10 @@ func TestBootstrapPartiallyAccepted(t *testing.T) { MaxItemProcessingTime: 1, }, Consensus: consensus, + + Peers: peers, + AncestorsMaxContainersSent: 2000, + AncestorsMaxContainersReceived: 2000, } engine, err := smeng.New(engineConfig) require.NoError(err) From 61ebecdbe6a553f1a42db29ba08ab3b98edd96e9 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 30 Oct 2023 23:03:14 +0100 Subject: [PATCH 20/36] temporarily cut coreth dependencies --- go.mod | 25 - go.sum | 76 -- node/node.go | 4 +- tests/e2e/c/dynamic_fees.go | 326 +++---- tests/e2e/c/interchain_workflow.go | 320 +++---- tests/e2e/e2e.go | 116 ++- tests/e2e/p/interchain_workflow.go | 444 +++++----- tests/e2e/x/interchain_workflow.go | 296 +++---- tests/fixture/testnet/config.go | 54 +- vms/example/xsvm/cmd/chain/create/cmd.go | 6 +- wallet/chain/c/backend.go | 300 +++---- wallet/chain/c/builder.go | 792 +++++++++--------- wallet/chain/c/builder_with_options.go | 136 +-- wallet/chain/c/context.go | 130 +-- wallet/chain/c/signer.go | 436 +++++----- wallet/chain/c/wallet.go | 402 ++++----- wallet/chain/c/wallet_with_options.go | 134 +-- wallet/subnet/primary/api.go | 119 ++- wallet/subnet/primary/example_test.go | 2 +- .../add-permissioned-subnet-validator/main.go | 6 +- .../examples/add-primary-validator/main.go | 2 +- .../primary/examples/c-chain-export/main.go | 118 +-- .../primary/examples/c-chain-import/main.go | 126 +-- .../primary/examples/create-asset/main.go | 2 +- .../primary/examples/create-chain/main.go | 6 +- .../examples/create-locked-stakeable/main.go | 2 +- .../primary/examples/create-subnet/main.go | 2 +- .../examples/remove-subnet-validator/main.go | 6 +- wallet/subnet/primary/wallet.go | 41 +- 29 files changed, 2154 insertions(+), 2275 deletions(-) diff --git a/go.mod b/go.mod index 8bcba0590042..40d59d0cb294 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,6 @@ require ( github.com/DataDog/zstd v1.5.2 github.com/Microsoft/go-winio v0.5.2 github.com/NYTimes/gziphandler v1.1.1 - github.com/ava-labs/coreth v0.12.8-0.20231027221814-507f2239095b github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 github.com/btcsuite/btcd/btcutil v1.1.3 github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 @@ -72,7 +71,6 @@ require ( require ( github.com/BurntSushi/toml v1.2.1 // indirect - github.com/VictoriaMetrics/fastcache v1.10.0 // indirect github.com/benbjohnson/clock v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect @@ -81,44 +79,26 @@ require ( github.com/cockroachdb/errors v1.9.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/redact v1.1.3 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/deckarep/golang-set/v2 v2.1.0 // indirect - github.com/dlclark/regexp2 v1.7.0 // indirect - github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect - github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/frankban/quicktest v1.14.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect - github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect - github.com/go-stack/stack v1.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect - github.com/google/uuid v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 // indirect - github.com/hashicorp/go-bexpr v0.1.10 // indirect - github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/klauspost/compress v1.15.15 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/magiconair/properties v1.8.6 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/mitchellh/pointerstructure v1.2.0 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect @@ -126,17 +106,12 @@ require ( github.com/prometheus/common v0.39.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sanity-io/litter v1.5.1 // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/status-im/keycard-go v0.2.0 // indirect github.com/subosito/gotenv v1.3.0 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect - github.com/tyler-smith/go-bip39 v1.1.0 // indirect - github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa // indirect - github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/zondax/hid v0.9.1 // indirect github.com/zondax/ledger-go v0.14.1 // indirect diff --git a/go.sum b/go.sum index f4d542b4a159..09e5526b3f20 100644 --- a/go.sum +++ b/go.sum @@ -52,18 +52,12 @@ github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cq github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= -github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY= -github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/ava-labs/coreth v0.12.8-0.20231027221814-507f2239095b h1:pKSpTTWvsmDJ7MUkaOPAYfN4mKgWgg4K2cm4k+tvqNI= -github.com/ava-labs/coreth v0.12.8-0.20231027221814-507f2239095b/go.mod h1:8aFn5vDkc9g7RT8bSvx9KAo2Xu4AqzwWAnfoderYPDs= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 h1:EdxD90j5sClfL5Ngpz2TlnbnkNYdFPDXa0jDOjam65c= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7/go.mod h1:XhiXSrh90sHUbkERzaxEftCmUz53eCijshDLZ4fByVM= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= @@ -100,18 +94,13 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -141,16 +130,12 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= -github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= @@ -161,14 +146,6 @@ github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6ps github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= -github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= -github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= -github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= -github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -185,8 +162,6 @@ github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2 github.com/ethereum/go-ethereum v1.12.0/go.mod h1:/oo2X/dZLJjf2mJ6YT9wcWxa4nNJDBKDBU6sFIpx1Gs= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -195,8 +170,6 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= @@ -220,11 +193,7 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= -github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= @@ -309,14 +278,10 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -337,17 +302,11 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 h1:kr3j8iIMR4ywO/O0rvksXaJvauGGCMg2zAZIiNZ9uIQ= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0/go.mod h1:ummNFgdgLhhX7aIiy35vVmQNS0rWXknfPE0qe6fmFXg= -github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= -github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e/go.mod h1:j9cQbcqHQujT0oKJ38PylVfqohClLr3CvDC+Qcg+lhU= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8= @@ -359,7 +318,6 @@ github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3 github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -401,7 +359,6 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -409,7 +366,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= @@ -420,17 +376,11 @@ github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -439,11 +389,8 @@ github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= -github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -462,8 +409,6 @@ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -531,8 +476,6 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sanity-io/litter v1.5.1 h1:dwnrSypP6q56o3lFxTU+t2fwQ9A+U5qrXVO4Qg9KwVU= github.com/sanity-io/litter v1.5.1/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0= @@ -568,8 +511,6 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= -github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= -github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -599,14 +540,10 @@ github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITn github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= -github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -618,8 +555,6 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1: github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= @@ -629,7 +564,6 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= @@ -727,7 +661,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -773,7 +706,6 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -797,7 +729,6 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -862,12 +793,8 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -884,7 +811,6 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -948,7 +874,6 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1073,7 +998,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= diff --git a/node/node.go b/node/node.go index 34293e85b0b6..3b3974db0401 100644 --- a/node/node.go +++ b/node/node.go @@ -25,7 +25,7 @@ import ( "go.uber.org/zap" - coreth "github.com/ava-labs/coreth/plugin/evm" + // coreth "github.com/ava-labs/coreth/plugin/evm" "github.com/ava-labs/avalanchego/api/admin" "github.com/ava-labs/avalanchego/api/auth" @@ -934,7 +934,7 @@ func (n *Node) initVMs() error { CreateAssetTxFee: n.Config.CreateAssetTxFee, }, }), - vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), + // vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), n.VMManager.RegisterFactory(context.TODO(), secp256k1fx.ID, &secp256k1fx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), nftfx.ID, &nftfx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), propertyfx.ID, &propertyfx.Factory{}), diff --git a/tests/e2e/c/dynamic_fees.go b/tests/e2e/c/dynamic_fees.go index edfbef2671a8..779c8670be37 100644 --- a/tests/e2e/c/dynamic_fees.go +++ b/tests/e2e/c/dynamic_fees.go @@ -3,166 +3,166 @@ package c -import ( - "math/big" - "strings" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/stretchr/testify/require" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/coreth/core/types" - "github.com/ava-labs/coreth/params" - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/tests" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/tests/fixture/testnet" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -) - -// This test uses the compiled bin for `hashing.sol` as -// well as its ABI contained in `hashing_contract.go`. - -var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { - require := require.New(ginkgo.GinkgoT()) - - // Need a gas limit much larger than the standard 21_000 to enable - // the contract to induce a gas price increase - const largeGasLimit = uint64(8_000_000) - - // TODO(marun) What is the significance of this value? - gasTip := big.NewInt(1000 * params.GWei) - - ginkgo.It("should ensure that the gas price is affected by load", func() { - ginkgo.By("creating a new private network to ensure isolation from other tests") - privateNetwork := e2e.Env.NewPrivateNetwork() - - ginkgo.By("allocating a pre-funded key") - key := privateNetwork.GetConfig().FundedKeys[0] - ethAddress := evm.GetEthAddress(key) - - ginkgo.By("initializing a coreth client") - node := privateNetwork.GetNodes()[0] - nodeURI := testnet.NodeURI{ - NodeID: node.GetID(), - URI: node.GetProcessContext().URI, - } - ethClient := e2e.Env.NewEthClient(nodeURI) - - ginkgo.By("initializing a transaction signer") - cChainID, err := ethClient.ChainID(e2e.DefaultContext()) - require.NoError(err) - signer := types.NewEIP155Signer(cChainID) - ecdsaKey := key.ToECDSA() - sign := func(tx *types.Transaction) *types.Transaction { - signedTx, err := types.SignTx(tx, signer, ecdsaKey) - require.NoError(err) - return signedTx - } - - var contractAddress common.Address - ginkgo.By("deploying an expensive contract", func() { - // Create transaction - nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) - require.NoError(err) - compiledContract := common.Hex2Bytes(hashingCompiledContract) - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - GasPrice: gasTip, - Gas: largeGasLimit, - Value: common.Big0, - Data: compiledContract, - }) - - // Send the transaction and wait for acceptance - signedTx := sign(tx) - receipt := e2e.SendEthTransaction(ethClient, signedTx) - - contractAddress = receipt.ContractAddress - }) - - var gasPrice *big.Int - ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { - // Evaluate the bytes representation of the contract - hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) - require.NoError(err) - contractData, err := hashingABI.Pack("hashIt") - require.NoError(err) - - var initialGasPrice *big.Int - e2e.Eventually(func() bool { - // Check the gas price - var err error - gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) - require.NoError(err) - if initialGasPrice == nil { - initialGasPrice = gasPrice - tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) - } else if gasPrice.Cmp(initialGasPrice) > 0 { - // Gas price has increased - tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) - return true - } - - // Create the transaction - nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) - require.NoError(err) - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - GasPrice: gasTip, - Gas: largeGasLimit, - To: &contractAddress, - Value: common.Big0, - Data: contractData, - }) - - // Send the transaction and wait for acceptance - signedTx := sign(tx) - _ = e2e.SendEthTransaction(ethClient, signedTx) - - // The gas price will be checked at the start of the next iteration - return false - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") - }) - - ginkgo.By("waiting for the gas price to decrease...", func() { - initialGasPrice := gasPrice - e2e.Eventually(func() bool { - var err error - gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) - require.NoError(err) - tests.Outf("{{blue}}.{{/}}") - return initialGasPrice.Cmp(gasPrice) > 0 - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") - tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) - }) - - ginkgo.By("sending funds at the current gas price", func() { - // Create a recipient address - recipientKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - recipientEthAddress := evm.GetEthAddress(recipientKey) - - // Create transaction - nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) - require.NoError(err) - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - GasPrice: gasPrice, - Gas: e2e.DefaultGasLimit, - To: &recipientEthAddress, - Value: common.Big0, - }) - - // Send the transaction and wait for acceptance - signedTx := sign(tx) - _ = e2e.SendEthTransaction(ethClient, signedTx) - }) - - e2e.CheckBootstrapIsPossible(privateNetwork) - }) -}) +// import ( +// "math/big" +// "strings" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/stretchr/testify/require" + +// "github.com/ethereum/go-ethereum/accounts/abi" +// "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/coreth/core/types" +// "github.com/ava-labs/coreth/params" +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/tests" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/tests/fixture/testnet" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// ) + +// // This test uses the compiled bin for `hashing.sol` as +// // well as its ABI contained in `hashing_contract.go`. + +// var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { +// require := require.New(ginkgo.GinkgoT()) + +// // Need a gas limit much larger than the standard 21_000 to enable +// // the contract to induce a gas price increase +// const largeGasLimit = uint64(8_000_000) + +// // TODO(marun) What is the significance of this value? +// gasTip := big.NewInt(1000 * params.GWei) + +// ginkgo.It("should ensure that the gas price is affected by load", func() { +// ginkgo.By("creating a new private network to ensure isolation from other tests") +// privateNetwork := e2e.Env.NewPrivateNetwork() + +// ginkgo.By("allocating a pre-funded key") +// key := privateNetwork.GetConfig().FundedKeys[0] +// ethAddress := evm.GetEthAddress(key) + +// ginkgo.By("initializing a coreth client") +// node := privateNetwork.GetNodes()[0] +// nodeURI := testnet.NodeURI{ +// NodeID: node.GetID(), +// URI: node.GetProcessContext().URI, +// } +// ethClient := e2e.Env.NewEthClient(nodeURI) + +// ginkgo.By("initializing a transaction signer") +// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) +// require.NoError(err) +// signer := types.NewEIP155Signer(cChainID) +// ecdsaKey := key.ToECDSA() +// sign := func(tx *types.Transaction) *types.Transaction { +// signedTx, err := types.SignTx(tx, signer, ecdsaKey) +// require.NoError(err) +// return signedTx +// } + +// var contractAddress common.Address +// ginkgo.By("deploying an expensive contract", func() { +// // Create transaction +// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) +// require.NoError(err) +// compiledContract := common.Hex2Bytes(hashingCompiledContract) +// tx := types.NewTx(&types.LegacyTx{ +// Nonce: nonce, +// GasPrice: gasTip, +// Gas: largeGasLimit, +// Value: common.Big0, +// Data: compiledContract, +// }) + +// // Send the transaction and wait for acceptance +// signedTx := sign(tx) +// receipt := e2e.SendEthTransaction(ethClient, signedTx) + +// contractAddress = receipt.ContractAddress +// }) + +// var gasPrice *big.Int +// ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { +// // Evaluate the bytes representation of the contract +// hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) +// require.NoError(err) +// contractData, err := hashingABI.Pack("hashIt") +// require.NoError(err) + +// var initialGasPrice *big.Int +// e2e.Eventually(func() bool { +// // Check the gas price +// var err error +// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) +// require.NoError(err) +// if initialGasPrice == nil { +// initialGasPrice = gasPrice +// tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) +// } else if gasPrice.Cmp(initialGasPrice) > 0 { +// // Gas price has increased +// tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) +// return true +// } + +// // Create the transaction +// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) +// require.NoError(err) +// tx := types.NewTx(&types.LegacyTx{ +// Nonce: nonce, +// GasPrice: gasTip, +// Gas: largeGasLimit, +// To: &contractAddress, +// Value: common.Big0, +// Data: contractData, +// }) + +// // Send the transaction and wait for acceptance +// signedTx := sign(tx) +// _ = e2e.SendEthTransaction(ethClient, signedTx) + +// // The gas price will be checked at the start of the next iteration +// return false +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") +// }) + +// ginkgo.By("waiting for the gas price to decrease...", func() { +// initialGasPrice := gasPrice +// e2e.Eventually(func() bool { +// var err error +// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) +// require.NoError(err) +// tests.Outf("{{blue}}.{{/}}") +// return initialGasPrice.Cmp(gasPrice) > 0 +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") +// tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) +// }) + +// ginkgo.By("sending funds at the current gas price", func() { +// // Create a recipient address +// recipientKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) +// recipientEthAddress := evm.GetEthAddress(recipientKey) + +// // Create transaction +// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) +// require.NoError(err) +// tx := types.NewTx(&types.LegacyTx{ +// Nonce: nonce, +// GasPrice: gasPrice, +// Gas: e2e.DefaultGasLimit, +// To: &recipientEthAddress, +// Value: common.Big0, +// }) + +// // Send the transaction and wait for acceptance +// signedTx := sign(tx) +// _ = e2e.SendEthTransaction(ethClient, signedTx) +// }) + +// e2e.CheckBootstrapIsPossible(privateNetwork) +// }) +// }) diff --git a/tests/e2e/c/interchain_workflow.go b/tests/e2e/c/interchain_workflow.go index 8bed85eb1bd9..d13c4b8db1ce 100644 --- a/tests/e2e/c/interchain_workflow.go +++ b/tests/e2e/c/interchain_workflow.go @@ -3,163 +3,163 @@ package c -import ( - "math/big" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/coreth/core/types" - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { - require := require.New(ginkgo.GinkgoT()) - - const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer - - ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { - ginkgo.By("initializing a new eth client") - // Select a random node URI to use for both the eth client and - // the wallet to avoid having to verify that all nodes are at - // the same height before initializing the wallet. - nodeURI := e2e.Env.GetRandomNodeURI() - ethClient := e2e.Env.NewEthClient(nodeURI) - - ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") - senderKey := e2e.Env.AllocateFundedKey() - senderEthAddress := evm.GetEthAddress(senderKey) - recipientKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - recipientEthAddress := evm.GetEthAddress(recipientKey) - - ginkgo.By("sending funds from one address to another on the C-Chain", func() { - // Create transaction - acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) - require.NoError(err) - gasPrice := e2e.SuggestGasPrice(ethClient) - tx := types.NewTransaction( - acceptedNonce, - recipientEthAddress, - big.NewInt(int64(txAmount)), - e2e.DefaultGasLimit, - gasPrice, - nil, - ) - - // Sign transaction - cChainID, err := ethClient.ChainID(e2e.DefaultContext()) - require.NoError(err) - signer := types.NewEIP155Signer(cChainID) - signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) - require.NoError(err) - - _ = e2e.SendEthTransaction(ethClient, signedTx) - - ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") - e2e.Eventually(func() bool { - balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) - require.NoError(err) - return balance.Cmp(big.NewInt(0)) > 0 - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") - }) - - // Wallet must be initialized after sending funds on the - // C-Chain with the same node URI to ensure wallet state - // matches on-chain state. - ginkgo.By("initializing a keychain and associated wallet") - keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) - baseWallet := e2e.Env.NewWallet(keychain, nodeURI) - xWallet := baseWallet.X() - cWallet := baseWallet.C() - pWallet := baseWallet.P() - - ginkgo.By("defining common configuration") - avaxAssetID := xWallet.AVAXAssetID() - // Use the same owner for import funds to X-Chain and P-Chain - recipientOwner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - recipientKey.Address(), - }, - } - // Use the same outputs for both X-Chain and P-Chain exports - exportOutputs := []*secp256k1fx.TransferOutput{ - { - Amt: txAmount, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - keychain.Keys[0].Address(), - }, - }, - }, - } - - ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { - _, err := cWallet.IssueExportTx( - xWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { - _, err := xWallet.IssueImportTx( - cWallet.BlockchainID(), - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { - balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { - _, err := cWallet.IssueExportTx( - constants.PlatformChainID, - exportOutputs, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { - _, err = pWallet.IssueImportTx( - cWallet.BlockchainID(), - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { - balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) - }) -}) +// import ( +// "math/big" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/stretchr/testify/require" + +// "github.com/ava-labs/coreth/core/types" +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { +// require := require.New(ginkgo.GinkgoT()) + +// const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer + +// ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { +// ginkgo.By("initializing a new eth client") +// // Select a random node URI to use for both the eth client and +// // the wallet to avoid having to verify that all nodes are at +// // the same height before initializing the wallet. +// nodeURI := e2e.Env.GetRandomNodeURI() +// ethClient := e2e.Env.NewEthClient(nodeURI) + +// ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") +// senderKey := e2e.Env.AllocateFundedKey() +// senderEthAddress := evm.GetEthAddress(senderKey) +// recipientKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) +// recipientEthAddress := evm.GetEthAddress(recipientKey) + +// ginkgo.By("sending funds from one address to another on the C-Chain", func() { +// // Create transaction +// acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) +// require.NoError(err) +// gasPrice := e2e.SuggestGasPrice(ethClient) +// tx := types.NewTransaction( +// acceptedNonce, +// recipientEthAddress, +// big.NewInt(int64(txAmount)), +// e2e.DefaultGasLimit, +// gasPrice, +// nil, +// ) + +// // Sign transaction +// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) +// require.NoError(err) +// signer := types.NewEIP155Signer(cChainID) +// signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) +// require.NoError(err) + +// _ = e2e.SendEthTransaction(ethClient, signedTx) + +// ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") +// e2e.Eventually(func() bool { +// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) +// require.NoError(err) +// return balance.Cmp(big.NewInt(0)) > 0 +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") +// }) + +// // Wallet must be initialized after sending funds on the +// // C-Chain with the same node URI to ensure wallet state +// // matches on-chain state. +// ginkgo.By("initializing a keychain and associated wallet") +// keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) +// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) +// xWallet := baseWallet.X() +// cWallet := baseWallet.C() +// pWallet := baseWallet.P() + +// ginkgo.By("defining common configuration") +// avaxAssetID := xWallet.AVAXAssetID() +// // Use the same owner for import funds to X-Chain and P-Chain +// recipientOwner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// recipientKey.Address(), +// }, +// } +// // Use the same outputs for both X-Chain and P-Chain exports +// exportOutputs := []*secp256k1fx.TransferOutput{ +// { +// Amt: txAmount, +// OutputOwners: secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// keychain.Keys[0].Address(), +// }, +// }, +// }, +// } + +// ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { +// _, err := cWallet.IssueExportTx( +// xWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { +// _, err := xWallet.IssueImportTx( +// cWallet.BlockchainID(), +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { +// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { +// _, err := cWallet.IssueExportTx( +// constants.PlatformChainID, +// exportOutputs, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { +// _, err = pWallet.IssueImportTx( +// cWallet.BlockchainID(), +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { +// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) +// }) +// }) diff --git a/tests/e2e/e2e.go b/tests/e2e/e2e.go index 130f33f1197c..8b70b9f9ca3f 100644 --- a/tests/e2e/e2e.go +++ b/tests/e2e/e2e.go @@ -7,23 +7,15 @@ package e2e import ( "context" "encoding/json" - "errors" - "fmt" - "math/big" "math/rand" "os" "path/filepath" - "strings" "time" ginkgo "github.com/onsi/ginkgo/v2" "github.com/stretchr/testify/require" - "github.com/ava-labs/coreth/core/types" - "github.com/ava-labs/coreth/ethclient" - "github.com/ava-labs/coreth/interfaces" - "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/tests" "github.com/ava-labs/avalanchego/tests/fixture" @@ -134,7 +126,7 @@ func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain, nodeURI tes baseWallet, err := primary.MakeWallet(DefaultContext(), &primary.WalletConfig{ URI: nodeURI.URI, AVAXKeychain: keychain, - EthKeychain: keychain, + // EthKeychain: keychain, }) te.require.NoError(err) return primary.NewWalletWithOptions( @@ -147,16 +139,16 @@ func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain, nodeURI tes ) } -// Create a new eth client targeting the specified node URI. -// TODO(marun) Make this a regular function. -func (te *TestEnvironment) NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { - tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) - nodeAddress := strings.Split(nodeURI.URI, "//")[1] - uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) - client, err := ethclient.Dial(uri) - te.require.NoError(err) - return client -} +// // Create a new eth client targeting the specified node URI. +// // TODO(marun) Make this a regular function. +// func (te *TestEnvironment) NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { +// tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) +// nodeAddress := strings.Split(nodeURI.URI, "//")[1] +// uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) +// client, err := ethclient.Dial(uri) +// te.require.NoError(err) +// return client +// } // Create a new private network that is not shared with other tests. func (te *TestEnvironment) NewPrivateNetwork() testnet.Network { @@ -231,49 +223,49 @@ func WaitForHealthy(node testnet.Node) { require.NoError(ginkgo.GinkgoT(), testnet.WaitForHealthy(DefaultContext(), node)) } -// Sends an eth transaction, waits for the transaction receipt to be issued -// and checks that the receipt indicates success. -func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { - require := require.New(ginkgo.GinkgoT()) - - txID := signedTx.Hash() - tests.Outf(" sending eth transaction with ID: %s\n", txID) - - require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) - - // Wait for the receipt - var receipt *types.Receipt - Eventually(func() bool { - var err error - receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) - if errors.Is(err, interfaces.NotFound) { - return false // Transaction is still pending - } - require.NoError(err) - return true - }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") - - require.Equal(receipt.Status, types.ReceiptStatusSuccessful) - return receipt -} - -// Determines the suggested gas price for the configured client that will -// maximize the chances of transaction acceptance. -func SuggestGasPrice(ethClient ethclient.Client) *big.Int { - gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) - require.NoError(ginkgo.GinkgoT(), err) - // Double the suggested gas price to maximize the chances of - // acceptance. Maybe this can be revisited pending resolution of - // https://github.com/ava-labs/coreth/issues/314. - gasPrice.Add(gasPrice, gasPrice) - return gasPrice -} - -// Helper simplifying use via an option of a gas price appropriate for testing. -func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { - baseFee := SuggestGasPrice(ethClient) - return common.WithBaseFee(baseFee) -} +// // Sends an eth transaction, waits for the transaction receipt to be issued +// // and checks that the receipt indicates success. +// func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { +// require := require.New(ginkgo.GinkgoT()) + +// txID := signedTx.Hash() +// tests.Outf(" sending eth transaction with ID: %s\n", txID) + +// require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) + +// // Wait for the receipt +// var receipt *types.Receipt +// Eventually(func() bool { +// var err error +// receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) +// if errors.Is(err, interfaces.NotFound) { +// return false // Transaction is still pending +// } +// require.NoError(err) +// return true +// }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") + +// require.Equal(receipt.Status, types.ReceiptStatusSuccessful) +// return receipt +// } + +// // Determines the suggested gas price for the configured client that will +// // maximize the chances of transaction acceptance. +// func SuggestGasPrice(ethClient ethclient.Client) *big.Int { +// gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) +// require.NoError(ginkgo.GinkgoT(), err) +// // Double the suggested gas price to maximize the chances of +// // acceptance. Maybe this can be revisited pending resolution of +// // https://github.com/ava-labs/coreth/issues/314. +// gasPrice.Add(gasPrice, gasPrice) +// return gasPrice +// } + +// // Helper simplifying use via an option of a gas price appropriate for testing. +// func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { +// baseFee := SuggestGasPrice(ethClient) +// return common.WithBaseFee(baseFee) +// } // Verify that a new node can bootstrap into the network. func CheckBootstrapIsPossible(network testnet.Network) { diff --git a/tests/e2e/p/interchain_workflow.go b/tests/e2e/p/interchain_workflow.go index 729418adbd97..d3715c254e90 100644 --- a/tests/e2e/p/interchain_workflow.go +++ b/tests/e2e/p/interchain_workflow.go @@ -3,225 +3,225 @@ package p -import ( - "math/big" - "time" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/spf13/cast" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/api/info" - "github.com/ava-labs/avalanchego/config" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/tests/fixture/testnet" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/platformvm/reward" - "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { - require := require.New(ginkgo.GinkgoT()) - - const ( - transferAmount = 10 * units.Avax - weight = 2_000 * units.Avax // Used for both validation and delegation - ) - - ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { - network := e2e.Env.GetNetwork() - - ginkgo.By("checking that the network has a compatible minimum stake duration", func() { - minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) - require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) - }) - - ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") - recipientKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - keychain := e2e.Env.NewKeychain(1) - keychain.Add(recipientKey) - nodeURI := e2e.Env.GetRandomNodeURI() - baseWallet := e2e.Env.NewWallet(keychain, nodeURI) - xWallet := baseWallet.X() - cWallet := baseWallet.C() - pWallet := baseWallet.P() - - ginkgo.By("defining common configuration") - recipientEthAddress := evm.GetEthAddress(recipientKey) - avaxAssetID := xWallet.AVAXAssetID() - // Use the same owner for sending to X-Chain and importing funds to P-Chain - recipientOwner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - recipientKey.Address(), - }, - } - // Use the same outputs for both X-Chain and C-Chain exports - exportOutputs := []*avax.TransferableOutput{ - { - Asset: avax.Asset{ - ID: avaxAssetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: transferAmount, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - keychain.Keys[0].Address(), - }, - }, - }, - }, - } - - ginkgo.By("adding new node and waiting for it to report healthy") - node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) - e2e.WaitForHealthy(node) - - ginkgo.By("retrieving new node's id and pop") - infoClient := info.NewClient(node.GetProcessContext().URI) - nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) - require.NoError(err) - - ginkgo.By("adding the new node as a validator", func() { - startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) - // Validation duration doesn't actually matter to this - // test - it is only ensuring that adding a validator - // doesn't break interchain transfer. - endTime := startTime.Add(30 * time.Second) - - rewardKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - - const ( - delegationPercent = 0.10 // 10% - delegationShare = reward.PercentDenominator * delegationPercent - ) - - _, err = pWallet.IssueAddPermissionlessValidatorTx( - &txs.SubnetValidator{ - Validator: txs.Validator{ - NodeID: nodeID, - Start: uint64(startTime.Unix()), - End: uint64(endTime.Unix()), - Wght: weight, - }, - Subnet: constants.PrimaryNetworkID, - }, - nodePOP, - pWallet.AVAXAssetID(), - &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{rewardKey.Address()}, - }, - &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{rewardKey.Address()}, - }, - delegationShare, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("adding a delegator to the new node", func() { - startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) - // Delegation duration doesn't actually matter to this - // test - it is only ensuring that adding a delegator - // doesn't break interchain transfer. - endTime := startTime.Add(15 * time.Second) - - rewardKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - - _, err = pWallet.IssueAddPermissionlessDelegatorTx( - &txs.SubnetValidator{ - Validator: txs.Validator{ - NodeID: nodeID, - Start: uint64(startTime.Unix()), - End: uint64(endTime.Unix()), - Wght: weight, - }, - Subnet: constants.PrimaryNetworkID, - }, - pWallet.AVAXAssetID(), - &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{rewardKey.Address()}, - }, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { - _, err := pWallet.IssueExportTx( - xWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { - _, err := xWallet.IssueImportTx( - constants.PlatformChainID, - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { - balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { - _, err := pWallet.IssueExportTx( - cWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("initializing a new eth client") - ethClient := e2e.Env.NewEthClient(nodeURI) - - ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { - _, err := cWallet.IssueImportTx( - constants.PlatformChainID, - recipientEthAddress, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") - balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) - require.NoError(err) - require.Positive(balance.Cmp(big.NewInt(0))) - - ginkgo.By("stopping validator node to free up resources for a bootstrap check") - require.NoError(node.Stop()) - - e2e.CheckBootstrapIsPossible(network) - }) -}) +// import ( +// "math/big" +// "time" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/spf13/cast" + +// "github.com/stretchr/testify/require" + +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/api/info" +// "github.com/ava-labs/avalanchego/config" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/tests/fixture/testnet" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/platformvm/reward" +// "github.com/ava-labs/avalanchego/vms/platformvm/txs" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { +// require := require.New(ginkgo.GinkgoT()) + +// const ( +// transferAmount = 10 * units.Avax +// weight = 2_000 * units.Avax // Used for both validation and delegation +// ) + +// ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { +// network := e2e.Env.GetNetwork() + +// ginkgo.By("checking that the network has a compatible minimum stake duration", func() { +// minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) +// require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) +// }) + +// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") +// recipientKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) +// keychain := e2e.Env.NewKeychain(1) +// keychain.Add(recipientKey) +// nodeURI := e2e.Env.GetRandomNodeURI() +// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) +// xWallet := baseWallet.X() +// cWallet := baseWallet.C() +// pWallet := baseWallet.P() + +// ginkgo.By("defining common configuration") +// recipientEthAddress := evm.GetEthAddress(recipientKey) +// avaxAssetID := xWallet.AVAXAssetID() +// // Use the same owner for sending to X-Chain and importing funds to P-Chain +// recipientOwner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// recipientKey.Address(), +// }, +// } +// // Use the same outputs for both X-Chain and C-Chain exports +// exportOutputs := []*avax.TransferableOutput{ +// { +// Asset: avax.Asset{ +// ID: avaxAssetID, +// }, +// Out: &secp256k1fx.TransferOutput{ +// Amt: transferAmount, +// OutputOwners: secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// keychain.Keys[0].Address(), +// }, +// }, +// }, +// }, +// } + +// ginkgo.By("adding new node and waiting for it to report healthy") +// node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) +// e2e.WaitForHealthy(node) + +// ginkgo.By("retrieving new node's id and pop") +// infoClient := info.NewClient(node.GetProcessContext().URI) +// nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) +// require.NoError(err) + +// ginkgo.By("adding the new node as a validator", func() { +// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) +// // Validation duration doesn't actually matter to this +// // test - it is only ensuring that adding a validator +// // doesn't break interchain transfer. +// endTime := startTime.Add(30 * time.Second) + +// rewardKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) + +// const ( +// delegationPercent = 0.10 // 10% +// delegationShare = reward.PercentDenominator * delegationPercent +// ) + +// _, err = pWallet.IssueAddPermissionlessValidatorTx( +// &txs.SubnetValidator{ +// Validator: txs.Validator{ +// NodeID: nodeID, +// Start: uint64(startTime.Unix()), +// End: uint64(endTime.Unix()), +// Wght: weight, +// }, +// Subnet: constants.PrimaryNetworkID, +// }, +// nodePOP, +// pWallet.AVAXAssetID(), +// &secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{rewardKey.Address()}, +// }, +// &secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{rewardKey.Address()}, +// }, +// delegationShare, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("adding a delegator to the new node", func() { +// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) +// // Delegation duration doesn't actually matter to this +// // test - it is only ensuring that adding a delegator +// // doesn't break interchain transfer. +// endTime := startTime.Add(15 * time.Second) + +// rewardKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) + +// _, err = pWallet.IssueAddPermissionlessDelegatorTx( +// &txs.SubnetValidator{ +// Validator: txs.Validator{ +// NodeID: nodeID, +// Start: uint64(startTime.Unix()), +// End: uint64(endTime.Unix()), +// Wght: weight, +// }, +// Subnet: constants.PrimaryNetworkID, +// }, +// pWallet.AVAXAssetID(), +// &secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{rewardKey.Address()}, +// }, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { +// _, err := pWallet.IssueExportTx( +// xWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { +// _, err := xWallet.IssueImportTx( +// constants.PlatformChainID, +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { +// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { +// _, err := pWallet.IssueExportTx( +// cWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("initializing a new eth client") +// ethClient := e2e.Env.NewEthClient(nodeURI) + +// ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { +// _, err := cWallet.IssueImportTx( +// constants.PlatformChainID, +// recipientEthAddress, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") +// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) +// require.NoError(err) +// require.Positive(balance.Cmp(big.NewInt(0))) + +// ginkgo.By("stopping validator node to free up resources for a bootstrap check") +// require.NoError(node.Stop()) + +// e2e.CheckBootstrapIsPossible(network) +// }) +// }) diff --git a/tests/e2e/x/interchain_workflow.go b/tests/e2e/x/interchain_workflow.go index 6d335199b5b9..3b7a4c988405 100644 --- a/tests/e2e/x/interchain_workflow.go +++ b/tests/e2e/x/interchain_workflow.go @@ -3,151 +3,151 @@ package x -import ( - "math/big" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { - require := require.New(ginkgo.GinkgoT()) - - const transferAmount = 10 * units.Avax - - ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { - nodeURI := e2e.Env.GetRandomNodeURI() - - ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") - recipientKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - keychain := e2e.Env.NewKeychain(1) - keychain.Add(recipientKey) - baseWallet := e2e.Env.NewWallet(keychain, nodeURI) - xWallet := baseWallet.X() - cWallet := baseWallet.C() - pWallet := baseWallet.P() - - ginkgo.By("defining common configuration") - recipientEthAddress := evm.GetEthAddress(recipientKey) - avaxAssetID := xWallet.AVAXAssetID() - // Use the same owner for sending to X-Chain and importing funds to P-Chain - recipientOwner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - recipientKey.Address(), - }, - } - // Use the same outputs for both C-Chain and P-Chain exports - exportOutputs := []*avax.TransferableOutput{ - { - Asset: avax.Asset{ - ID: avaxAssetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: transferAmount, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - keychain.Keys[0].Address(), - }, - }, - }, - }, - } - - ginkgo.By("sending funds from one address to another on the X-Chain", func() { - _, err = xWallet.IssueBaseTx( - []*avax.TransferableOutput{{ - Asset: avax.Asset{ - ID: avaxAssetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: transferAmount, - OutputOwners: recipientOwner, - }, - }}, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { - balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { - _, err := xWallet.IssueExportTx( - cWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("initializing a new eth client") - ethClient := e2e.Env.NewEthClient(nodeURI) - - ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { - _, err := cWallet.IssueImportTx( - xWallet.BlockchainID(), - recipientEthAddress, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") - e2e.Eventually(func() bool { - balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) - require.NoError(err) - return balance.Cmp(big.NewInt(0)) > 0 - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") - - ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { - _, err := xWallet.IssueExportTx( - constants.PlatformChainID, - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { - _, err := pWallet.IssueImportTx( - xWallet.BlockchainID(), - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { - balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) - }) -}) +// import ( +// "math/big" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/stretchr/testify/require" + +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { +// require := require.New(ginkgo.GinkgoT()) + +// const transferAmount = 10 * units.Avax + +// ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { +// nodeURI := e2e.Env.GetRandomNodeURI() + +// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") +// recipientKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) +// keychain := e2e.Env.NewKeychain(1) +// keychain.Add(recipientKey) +// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) +// xWallet := baseWallet.X() +// cWallet := baseWallet.C() +// pWallet := baseWallet.P() + +// ginkgo.By("defining common configuration") +// recipientEthAddress := evm.GetEthAddress(recipientKey) +// avaxAssetID := xWallet.AVAXAssetID() +// // Use the same owner for sending to X-Chain and importing funds to P-Chain +// recipientOwner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// recipientKey.Address(), +// }, +// } +// // Use the same outputs for both C-Chain and P-Chain exports +// exportOutputs := []*avax.TransferableOutput{ +// { +// Asset: avax.Asset{ +// ID: avaxAssetID, +// }, +// Out: &secp256k1fx.TransferOutput{ +// Amt: transferAmount, +// OutputOwners: secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// keychain.Keys[0].Address(), +// }, +// }, +// }, +// }, +// } + +// ginkgo.By("sending funds from one address to another on the X-Chain", func() { +// _, err = xWallet.IssueBaseTx( +// []*avax.TransferableOutput{{ +// Asset: avax.Asset{ +// ID: avaxAssetID, +// }, +// Out: &secp256k1fx.TransferOutput{ +// Amt: transferAmount, +// OutputOwners: recipientOwner, +// }, +// }}, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { +// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { +// _, err := xWallet.IssueExportTx( +// cWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("initializing a new eth client") +// ethClient := e2e.Env.NewEthClient(nodeURI) + +// ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { +// _, err := cWallet.IssueImportTx( +// xWallet.BlockchainID(), +// recipientEthAddress, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") +// e2e.Eventually(func() bool { +// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) +// require.NoError(err) +// return balance.Cmp(big.NewInt(0)) > 0 +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") + +// ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { +// _, err := xWallet.IssueExportTx( +// constants.PlatformChainID, +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { +// _, err := pWallet.IssueImportTx( +// xWallet.BlockchainID(), +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { +// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) +// }) +// }) diff --git a/tests/fixture/testnet/config.go b/tests/fixture/testnet/config.go index 425aa646a690..0f24b60b50db 100644 --- a/tests/fixture/testnet/config.go +++ b/tests/fixture/testnet/config.go @@ -15,10 +15,6 @@ import ( "github.com/spf13/cast" - "github.com/ava-labs/coreth/core" - "github.com/ava-labs/coreth/params" - "github.com/ava-labs/coreth/plugin/evm" - "github.com/ava-labs/avalanchego/config" "github.com/ava-labs/avalanchego/genesis" "github.com/ava-labs/avalanchego/ids" @@ -143,15 +139,15 @@ func (c *NetworkConfig) EnsureGenesis(networkID uint32, validatorIDs []ids.NodeI // Ensure pre-funded keys have arbitrary large balances on both chains to support testing xChainBalances := make(XChainBalanceMap, len(c.FundedKeys)) - cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) - for _, key := range c.FundedKeys { - xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount - cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ - Balance: DefaultFundedKeyCChainAmount, - } - } - - genesis, err := NewTestGenesis(networkID, xChainBalances, cChainBalances, validatorIDs) + // cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) + // for _, key := range c.FundedKeys { + // xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount + // cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ + // Balance: DefaultFundedKeyCChainAmount, + // } + // } + + genesis, err := NewTestGenesis(networkID, xChainBalances /*, cChainBalances*/, validatorIDs) if err != nil { return err } @@ -311,7 +307,7 @@ type XChainBalanceMap map[ids.ShortID]uint64 func NewTestGenesis( networkID uint32, xChainBalances XChainBalanceMap, - cChainBalances core.GenesisAlloc, + // cChainBalances core.GenesisAlloc, validatorIDs []ids.NodeID, ) (*genesis.UnparsedConfig, error) { // Validate inputs @@ -322,7 +318,7 @@ func NewTestGenesis( if len(validatorIDs) == 0 { return nil, errMissingValidatorsForGenesis } - if len(xChainBalances) == 0 || len(cChainBalances) == 0 { + if len(xChainBalances) == 0 /*|| len(cChainBalances) == 0*/ { return nil, errMissingBalancesForGenesis } @@ -394,20 +390,20 @@ func NewTestGenesis( ) } - // Define C-Chain genesis - cChainGenesis := &core.Genesis{ - Config: ¶ms.ChainConfig{ - ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary - }, - Difficulty: big.NewInt(0), // Difficulty is a mandatory field - GasLimit: DefaultGasLimit, - Alloc: cChainBalances, - } - cChainGenesisBytes, err := json.Marshal(cChainGenesis) - if err != nil { - return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) - } - config.CChainGenesis = string(cChainGenesisBytes) + // // Define C-Chain genesis + // cChainGenesis := &core.Genesis{ + // Config: ¶ms.ChainConfig{ + // ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary + // }, + // Difficulty: big.NewInt(0), // Difficulty is a mandatory field + // GasLimit: DefaultGasLimit, + // // Alloc: cChainBalances, + // } + // cChainGenesisBytes, err := json.Marshal(cChainGenesis) + // if err != nil { + // return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) + // } + // config.CChainGenesis = string(cChainGenesisBytes) // Give staking rewards for initial validators to a random address. Any testing of staking rewards // will be easier to perform with nodes other than the initial validators since the timing of diff --git a/vms/example/xsvm/cmd/chain/create/cmd.go b/vms/example/xsvm/cmd/chain/create/cmd.go index 1f00491a4ce6..043b4298dcdf 100644 --- a/vms/example/xsvm/cmd/chain/create/cmd.go +++ b/vms/example/xsvm/cmd/chain/create/cmd.go @@ -42,9 +42,9 @@ func createFunc(c *cobra.Command, args []string) error { // that [uri] is hosting. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: config.URI, - AVAXKeychain: kc, - EthKeychain: kc, + URI: config.URI, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(config.SubnetID), }) if err != nil { diff --git a/wallet/chain/c/backend.go b/wallet/chain/c/backend.go index 0a735116b646..b88c8c643bc3 100644 --- a/wallet/chain/c/backend.go +++ b/wallet/chain/c/backend.go @@ -3,153 +3,153 @@ package c -import ( - "errors" - "fmt" - "math/big" - "sync" - - stdcontext "context" - - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/utils/math" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var ( - _ Backend = (*backend)(nil) - - errUnknownTxType = errors.New("unknown tx type") -) - -// Backend defines the full interface required to support a C-chain wallet. -type Backend interface { - common.ChainUTXOs - BuilderBackend - SignerBackend - - AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error -} - -type backend struct { - Context - common.ChainUTXOs - - accountsLock sync.RWMutex - accounts map[ethcommon.Address]*Account -} - -type Account struct { - Balance *big.Int - Nonce uint64 -} - -func NewBackend( - ctx Context, - utxos common.ChainUTXOs, - accounts map[ethcommon.Address]*Account, -) Backend { - return &backend{ - Context: ctx, - ChainUTXOs: utxos, - accounts: accounts, - } -} - -func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { - switch tx := tx.UnsignedAtomicTx.(type) { - case *evm.UnsignedImportTx: - for _, input := range tx.ImportedInputs { - utxoID := input.InputID() - if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { - return err - } - } - - b.accountsLock.Lock() - defer b.accountsLock.Unlock() - - for _, output := range tx.Outs { - account, ok := b.accounts[output.Address] - if !ok { - continue - } - - balance := new(big.Int).SetUint64(output.Amount) - balance.Mul(balance, avaxConversionRate) - account.Balance.Add(account.Balance, balance) - } - case *evm.UnsignedExportTx: - txID := tx.ID() - for i, out := range tx.ExportedOutputs { - err := b.AddUTXO( - ctx, - tx.DestinationChain, - &avax.UTXO{ - UTXOID: avax.UTXOID{ - TxID: txID, - OutputIndex: uint32(i), - }, - Asset: avax.Asset{ID: out.AssetID()}, - Out: out.Out, - }, - ) - if err != nil { - return err - } - } - - b.accountsLock.Lock() - defer b.accountsLock.Unlock() - - for _, input := range tx.Ins { - account, ok := b.accounts[input.Address] - if !ok { - continue - } - - balance := new(big.Int).SetUint64(input.Amount) - balance.Mul(balance, avaxConversionRate) - if account.Balance.Cmp(balance) == -1 { - return errInsufficientFunds - } - account.Balance.Sub(account.Balance, balance) - - newNonce, err := math.Add64(input.Nonce, 1) - if err != nil { - return err - } - account.Nonce = newNonce - } - default: - return fmt.Errorf("%w: %T", errUnknownTxType, tx) - } - return nil -} - -func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { - b.accountsLock.RLock() - defer b.accountsLock.RUnlock() - - account, exists := b.accounts[addr] - if !exists { - return nil, database.ErrNotFound - } - return account.Balance, nil -} - -func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { - b.accountsLock.RLock() - defer b.accountsLock.RUnlock() - - account, exists := b.accounts[addr] - if !exists { - return 0, database.ErrNotFound - } - return account.Nonce, nil -} +// import ( +// "errors" +// "fmt" +// "math/big" +// "sync" + +// stdcontext "context" + +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/database" +// "github.com/ava-labs/avalanchego/utils/math" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var ( +// _ Backend = (*backend)(nil) + +// errUnknownTxType = errors.New("unknown tx type") +// ) + +// // Backend defines the full interface required to support a C-chain wallet. +// type Backend interface { +// common.ChainUTXOs +// BuilderBackend +// SignerBackend + +// AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error +// } + +// type backend struct { +// Context +// common.ChainUTXOs + +// accountsLock sync.RWMutex +// accounts map[ethcommon.Address]*Account +// } + +// type Account struct { +// Balance *big.Int +// Nonce uint64 +// } + +// func NewBackend( +// ctx Context, +// utxos common.ChainUTXOs, +// accounts map[ethcommon.Address]*Account, +// ) Backend { +// return &backend{ +// Context: ctx, +// ChainUTXOs: utxos, +// accounts: accounts, +// } +// } + +// func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { +// switch tx := tx.UnsignedAtomicTx.(type) { +// case *evm.UnsignedImportTx: +// for _, input := range tx.ImportedInputs { +// utxoID := input.InputID() +// if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { +// return err +// } +// } + +// b.accountsLock.Lock() +// defer b.accountsLock.Unlock() + +// for _, output := range tx.Outs { +// account, ok := b.accounts[output.Address] +// if !ok { +// continue +// } + +// balance := new(big.Int).SetUint64(output.Amount) +// balance.Mul(balance, avaxConversionRate) +// account.Balance.Add(account.Balance, balance) +// } +// case *evm.UnsignedExportTx: +// txID := tx.ID() +// for i, out := range tx.ExportedOutputs { +// err := b.AddUTXO( +// ctx, +// tx.DestinationChain, +// &avax.UTXO{ +// UTXOID: avax.UTXOID{ +// TxID: txID, +// OutputIndex: uint32(i), +// }, +// Asset: avax.Asset{ID: out.AssetID()}, +// Out: out.Out, +// }, +// ) +// if err != nil { +// return err +// } +// } + +// b.accountsLock.Lock() +// defer b.accountsLock.Unlock() + +// for _, input := range tx.Ins { +// account, ok := b.accounts[input.Address] +// if !ok { +// continue +// } + +// balance := new(big.Int).SetUint64(input.Amount) +// balance.Mul(balance, avaxConversionRate) +// if account.Balance.Cmp(balance) == -1 { +// return errInsufficientFunds +// } +// account.Balance.Sub(account.Balance, balance) + +// newNonce, err := math.Add64(input.Nonce, 1) +// if err != nil { +// return err +// } +// account.Nonce = newNonce +// } +// default: +// return fmt.Errorf("%w: %T", errUnknownTxType, tx) +// } +// return nil +// } + +// func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { +// b.accountsLock.RLock() +// defer b.accountsLock.RUnlock() + +// account, exists := b.accounts[addr] +// if !exists { +// return nil, database.ErrNotFound +// } +// return account.Balance, nil +// } + +// func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { +// b.accountsLock.RLock() +// defer b.accountsLock.RUnlock() + +// account, exists := b.accounts[addr] +// if !exists { +// return 0, database.ErrNotFound +// } +// return account.Nonce, nil +// } diff --git a/wallet/chain/c/builder.go b/wallet/chain/c/builder.go index d2d088e88a53..c51d2647777e 100644 --- a/wallet/chain/c/builder.go +++ b/wallet/chain/c/builder.go @@ -3,399 +3,399 @@ package c -import ( - "errors" - "math/big" - - stdcontext "context" - - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils" - "github.com/ava-labs/avalanchego/utils/math" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -const avaxConversionRateInt = 1_000_000_000 - -var ( - _ Builder = (*builder)(nil) - - errInsufficientFunds = errors.New("insufficient funds") - - // avaxConversionRate is the conversion rate between the smallest - // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest - // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. - // - // This is only required for AVAX because the denomination of 1 AVAX is 9 - // decimal places on the X and P chains, but is 18 decimal places within the - // EVM. - avaxConversionRate = big.NewInt(avaxConversionRateInt) -) - -// Builder provides a convenient interface for building unsigned C-chain -// transactions. -type Builder interface { - // GetBalance calculates the amount of AVAX that this builder has control - // over. - GetBalance( - options ...common.Option, - ) (*big.Int, error) - - // GetImportableBalance calculates the amount of AVAX that this builder - // could import from the provided chain. - // - // - [chainID] specifies the chain the funds are from. - GetImportableBalance( - chainID ids.ID, - options ...common.Option, - ) (uint64, error) - - // NewImportTx creates an import transaction that attempts to consume all - // the available UTXOs and import the funds to [to]. - // - // - [chainID] specifies the chain to be importing funds from. - // - [to] specifies where to send the imported funds to. - // - [baseFee] specifies the fee price willing to be paid by this tx. - NewImportTx( - chainID ids.ID, - to ethcommon.Address, - baseFee *big.Int, - options ...common.Option, - ) (*evm.UnsignedImportTx, error) - - // NewExportTx creates an export transaction that attempts to send all the - // provided [outputs] to the requested [chainID]. - // - // - [chainID] specifies the chain to be exporting the funds to. - // - [outputs] specifies the outputs to send to the [chainID]. - // - [baseFee] specifies the fee price willing to be paid by this tx. - NewExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - baseFee *big.Int, - options ...common.Option, - ) (*evm.UnsignedExportTx, error) -} - -// BuilderBackend specifies the required information needed to build unsigned -// C-chain transactions. -type BuilderBackend interface { - Context - - UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) - Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) - Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) -} - -type builder struct { - avaxAddrs set.Set[ids.ShortID] - ethAddrs set.Set[ethcommon.Address] - backend BuilderBackend -} - -// NewBuilder returns a new transaction builder. -// -// - [avaxAddrs] is the set of addresses in the AVAX format that the builder -// assumes can be used when signing the transactions in the future. -// - [ethAddrs] is the set of addresses in the Eth format that the builder -// assumes can be used when signing the transactions in the future. -// - [backend] provides the required access to the chain's context and state -// to build out the transactions. -func NewBuilder( - avaxAddrs set.Set[ids.ShortID], - ethAddrs set.Set[ethcommon.Address], - backend BuilderBackend, -) Builder { - return &builder{ - avaxAddrs: avaxAddrs, - ethAddrs: ethAddrs, - backend: backend, - } -} - -func (b *builder) GetBalance( - options ...common.Option, -) (*big.Int, error) { - var ( - ops = common.NewOptions(options) - ctx = ops.Context() - addrs = ops.EthAddresses(b.ethAddrs) - totalBalance = new(big.Int) - ) - for addr := range addrs { - balance, err := b.backend.Balance(ctx, addr) - if err != nil { - return nil, err - } - totalBalance.Add(totalBalance, balance) - } - - return totalBalance, nil -} - -func (b *builder) GetImportableBalance( - chainID ids.ID, - options ...common.Option, -) (uint64, error) { - ops := common.NewOptions(options) - utxos, err := b.backend.UTXOs(ops.Context(), chainID) - if err != nil { - return 0, err - } - - var ( - addrs = ops.Addresses(b.avaxAddrs) - minIssuanceTime = ops.MinIssuanceTime() - avaxAssetID = b.backend.AVAXAssetID() - balance uint64 - ) - for _, utxo := range utxos { - amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) - if !ok { - continue - } - - newBalance, err := math.Add64(balance, amount) - if err != nil { - return 0, err - } - balance = newBalance - } - - return balance, nil -} - -func (b *builder) NewImportTx( - chainID ids.ID, - to ethcommon.Address, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedImportTx, error) { - ops := common.NewOptions(options) - utxos, err := b.backend.UTXOs(ops.Context(), chainID) - if err != nil { - return nil, err - } - - var ( - addrs = ops.Addresses(b.avaxAddrs) - minIssuanceTime = ops.MinIssuanceTime() - avaxAssetID = b.backend.AVAXAssetID() - - importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) - importedAmount uint64 - ) - for _, utxo := range utxos { - amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) - if !ok { - continue - } - - importedInputs = append(importedInputs, &avax.TransferableInput{ - UTXOID: utxo.UTXOID, - Asset: utxo.Asset, - In: &secp256k1fx.TransferInput{ - Amt: amount, - Input: secp256k1fx.Input{ - SigIndices: inputSigIndices, - }, - }, - }) - - newImportedAmount, err := math.Add64(importedAmount, amount) - if err != nil { - return nil, err - } - importedAmount = newImportedAmount - } - - utils.Sort(importedInputs) - tx := &evm.UnsignedImportTx{ - NetworkID: b.backend.NetworkID(), - BlockchainID: b.backend.BlockchainID(), - SourceChain: chainID, - ImportedInputs: importedInputs, - } - - // We must initialize the bytes of the tx to calculate the initial cost - wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} - if err := wrappedTx.Sign(evm.Codec, nil); err != nil { - return nil, err - } - - gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) - if err != nil { - return nil, err - } - gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas - - txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) - if err != nil { - return nil, err - } - - if importedAmount <= txFee { - return nil, errInsufficientFunds - } - - tx.Outs = []evm.EVMOutput{{ - Address: to, - Amount: importedAmount - txFee, - AssetID: avaxAssetID, - }} - return tx, nil -} - -func (b *builder) NewExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedExportTx, error) { - var ( - avaxAssetID = b.backend.AVAXAssetID() - exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) - exportedAmount uint64 - ) - for i, output := range outputs { - exportedOutputs[i] = &avax.TransferableOutput{ - Asset: avax.Asset{ID: avaxAssetID}, - Out: output, - } - - newExportedAmount, err := math.Add64(exportedAmount, output.Amt) - if err != nil { - return nil, err - } - exportedAmount = newExportedAmount - } - - avax.SortTransferableOutputs(exportedOutputs, evm.Codec) - tx := &evm.UnsignedExportTx{ - NetworkID: b.backend.NetworkID(), - BlockchainID: b.backend.BlockchainID(), - DestinationChain: chainID, - ExportedOutputs: exportedOutputs, - } - - // We must initialize the bytes of the tx to calculate the initial cost - wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} - if err := wrappedTx.Sign(evm.Codec, nil); err != nil { - return nil, err - } - - cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) - if err != nil { - return nil, err - } - - initialFee, err := evm.CalculateDynamicFee(cost, baseFee) - if err != nil { - return nil, err - } - - amountToConsume, err := math.Add64(exportedAmount, initialFee) - if err != nil { - return nil, err - } - - var ( - ops = common.NewOptions(options) - ctx = ops.Context() - addrs = ops.EthAddresses(b.ethAddrs) - inputs = make([]evm.EVMInput, 0, addrs.Len()) - ) - for addr := range addrs { - if amountToConsume == 0 { - break - } - - prevFee, err := evm.CalculateDynamicFee(cost, baseFee) - if err != nil { - return nil, err - } - - newCost := cost + evm.EVMInputGas - newFee, err := evm.CalculateDynamicFee(newCost, baseFee) - if err != nil { - return nil, err - } - - additionalFee := newFee - prevFee - - balance, err := b.backend.Balance(ctx, addr) - if err != nil { - return nil, err - } - - // Since the asset is AVAX, we divide by the avaxConversionRate to - // convert back to the correct denomination of AVAX that can be - // exported. - avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() - - // If the balance for [addr] is insufficient to cover the additional - // cost of adding an input to the transaction, skip adding the input - // altogether. - if avaxBalance <= additionalFee { - continue - } - - // Update the cost for the next iteration - cost = newCost - - amountToConsume, err = math.Add64(amountToConsume, additionalFee) - if err != nil { - return nil, err - } - - nonce, err := b.backend.Nonce(ctx, addr) - if err != nil { - return nil, err - } - - inputAmount := math.Min(amountToConsume, avaxBalance) - inputs = append(inputs, evm.EVMInput{ - Address: addr, - Amount: inputAmount, - AssetID: avaxAssetID, - Nonce: nonce, - }) - amountToConsume -= inputAmount - } - - if amountToConsume > 0 { - return nil, errInsufficientFunds - } - - utils.Sort(inputs) - tx.Ins = inputs - return tx, nil -} - -func getSpendableAmount( - utxo *avax.UTXO, - addrs set.Set[ids.ShortID], - minIssuanceTime uint64, - avaxAssetID ids.ID, -) (uint64, []uint32, bool) { - if utxo.Asset.ID != avaxAssetID { - // Only AVAX can be imported - return 0, nil, false - } - - out, ok := utxo.Out.(*secp256k1fx.TransferOutput) - if !ok { - // Can't import an unknown transfer output type - return 0, nil, false - } - - inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) - return out.Amt, inputSigIndices, ok -} +// import ( +// "errors" +// "math/big" + +// stdcontext "context" + +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils" +// "github.com/ava-labs/avalanchego/utils/math" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// const avaxConversionRateInt = 1_000_000_000 + +// var ( +// _ Builder = (*builder)(nil) + +// errInsufficientFunds = errors.New("insufficient funds") + +// // avaxConversionRate is the conversion rate between the smallest +// // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest +// // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. +// // +// // This is only required for AVAX because the denomination of 1 AVAX is 9 +// // decimal places on the X and P chains, but is 18 decimal places within the +// // EVM. +// avaxConversionRate = big.NewInt(avaxConversionRateInt) +// ) + +// // Builder provides a convenient interface for building unsigned C-chain +// // transactions. +// type Builder interface { +// // GetBalance calculates the amount of AVAX that this builder has control +// // over. +// GetBalance( +// options ...common.Option, +// ) (*big.Int, error) + +// // GetImportableBalance calculates the amount of AVAX that this builder +// // could import from the provided chain. +// // +// // - [chainID] specifies the chain the funds are from. +// GetImportableBalance( +// chainID ids.ID, +// options ...common.Option, +// ) (uint64, error) + +// // NewImportTx creates an import transaction that attempts to consume all +// // the available UTXOs and import the funds to [to]. +// // +// // - [chainID] specifies the chain to be importing funds from. +// // - [to] specifies where to send the imported funds to. +// // - [baseFee] specifies the fee price willing to be paid by this tx. +// NewImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedImportTx, error) + +// // NewExportTx creates an export transaction that attempts to send all the +// // provided [outputs] to the requested [chainID]. +// // +// // - [chainID] specifies the chain to be exporting the funds to. +// // - [outputs] specifies the outputs to send to the [chainID]. +// // - [baseFee] specifies the fee price willing to be paid by this tx. +// NewExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedExportTx, error) +// } + +// // BuilderBackend specifies the required information needed to build unsigned +// // C-chain transactions. +// type BuilderBackend interface { +// Context + +// UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) +// Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) +// Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) +// } + +// type builder struct { +// avaxAddrs set.Set[ids.ShortID] +// ethAddrs set.Set[ethcommon.Address] +// backend BuilderBackend +// } + +// // NewBuilder returns a new transaction builder. +// // +// // - [avaxAddrs] is the set of addresses in the AVAX format that the builder +// // assumes can be used when signing the transactions in the future. +// // - [ethAddrs] is the set of addresses in the Eth format that the builder +// // assumes can be used when signing the transactions in the future. +// // - [backend] provides the required access to the chain's context and state +// // to build out the transactions. +// func NewBuilder( +// avaxAddrs set.Set[ids.ShortID], +// ethAddrs set.Set[ethcommon.Address], +// backend BuilderBackend, +// ) Builder { +// return &builder{ +// avaxAddrs: avaxAddrs, +// ethAddrs: ethAddrs, +// backend: backend, +// } +// } + +// func (b *builder) GetBalance( +// options ...common.Option, +// ) (*big.Int, error) { +// var ( +// ops = common.NewOptions(options) +// ctx = ops.Context() +// addrs = ops.EthAddresses(b.ethAddrs) +// totalBalance = new(big.Int) +// ) +// for addr := range addrs { +// balance, err := b.backend.Balance(ctx, addr) +// if err != nil { +// return nil, err +// } +// totalBalance.Add(totalBalance, balance) +// } + +// return totalBalance, nil +// } + +// func (b *builder) GetImportableBalance( +// chainID ids.ID, +// options ...common.Option, +// ) (uint64, error) { +// ops := common.NewOptions(options) +// utxos, err := b.backend.UTXOs(ops.Context(), chainID) +// if err != nil { +// return 0, err +// } + +// var ( +// addrs = ops.Addresses(b.avaxAddrs) +// minIssuanceTime = ops.MinIssuanceTime() +// avaxAssetID = b.backend.AVAXAssetID() +// balance uint64 +// ) +// for _, utxo := range utxos { +// amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) +// if !ok { +// continue +// } + +// newBalance, err := math.Add64(balance, amount) +// if err != nil { +// return 0, err +// } +// balance = newBalance +// } + +// return balance, nil +// } + +// func (b *builder) NewImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedImportTx, error) { +// ops := common.NewOptions(options) +// utxos, err := b.backend.UTXOs(ops.Context(), chainID) +// if err != nil { +// return nil, err +// } + +// var ( +// addrs = ops.Addresses(b.avaxAddrs) +// minIssuanceTime = ops.MinIssuanceTime() +// avaxAssetID = b.backend.AVAXAssetID() + +// importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) +// importedAmount uint64 +// ) +// for _, utxo := range utxos { +// amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) +// if !ok { +// continue +// } + +// importedInputs = append(importedInputs, &avax.TransferableInput{ +// UTXOID: utxo.UTXOID, +// Asset: utxo.Asset, +// In: &secp256k1fx.TransferInput{ +// Amt: amount, +// Input: secp256k1fx.Input{ +// SigIndices: inputSigIndices, +// }, +// }, +// }) + +// newImportedAmount, err := math.Add64(importedAmount, amount) +// if err != nil { +// return nil, err +// } +// importedAmount = newImportedAmount +// } + +// utils.Sort(importedInputs) +// tx := &evm.UnsignedImportTx{ +// NetworkID: b.backend.NetworkID(), +// BlockchainID: b.backend.BlockchainID(), +// SourceChain: chainID, +// ImportedInputs: importedInputs, +// } + +// // We must initialize the bytes of the tx to calculate the initial cost +// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} +// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { +// return nil, err +// } + +// gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) +// if err != nil { +// return nil, err +// } +// gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas + +// txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) +// if err != nil { +// return nil, err +// } + +// if importedAmount <= txFee { +// return nil, errInsufficientFunds +// } + +// tx.Outs = []evm.EVMOutput{{ +// Address: to, +// Amount: importedAmount - txFee, +// AssetID: avaxAssetID, +// }} +// return tx, nil +// } + +// func (b *builder) NewExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedExportTx, error) { +// var ( +// avaxAssetID = b.backend.AVAXAssetID() +// exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) +// exportedAmount uint64 +// ) +// for i, output := range outputs { +// exportedOutputs[i] = &avax.TransferableOutput{ +// Asset: avax.Asset{ID: avaxAssetID}, +// Out: output, +// } + +// newExportedAmount, err := math.Add64(exportedAmount, output.Amt) +// if err != nil { +// return nil, err +// } +// exportedAmount = newExportedAmount +// } + +// avax.SortTransferableOutputs(exportedOutputs, evm.Codec) +// tx := &evm.UnsignedExportTx{ +// NetworkID: b.backend.NetworkID(), +// BlockchainID: b.backend.BlockchainID(), +// DestinationChain: chainID, +// ExportedOutputs: exportedOutputs, +// } + +// // We must initialize the bytes of the tx to calculate the initial cost +// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} +// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { +// return nil, err +// } + +// cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) +// if err != nil { +// return nil, err +// } + +// initialFee, err := evm.CalculateDynamicFee(cost, baseFee) +// if err != nil { +// return nil, err +// } + +// amountToConsume, err := math.Add64(exportedAmount, initialFee) +// if err != nil { +// return nil, err +// } + +// var ( +// ops = common.NewOptions(options) +// ctx = ops.Context() +// addrs = ops.EthAddresses(b.ethAddrs) +// inputs = make([]evm.EVMInput, 0, addrs.Len()) +// ) +// for addr := range addrs { +// if amountToConsume == 0 { +// break +// } + +// prevFee, err := evm.CalculateDynamicFee(cost, baseFee) +// if err != nil { +// return nil, err +// } + +// newCost := cost + evm.EVMInputGas +// newFee, err := evm.CalculateDynamicFee(newCost, baseFee) +// if err != nil { +// return nil, err +// } + +// additionalFee := newFee - prevFee + +// balance, err := b.backend.Balance(ctx, addr) +// if err != nil { +// return nil, err +// } + +// // Since the asset is AVAX, we divide by the avaxConversionRate to +// // convert back to the correct denomination of AVAX that can be +// // exported. +// avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() + +// // If the balance for [addr] is insufficient to cover the additional +// // cost of adding an input to the transaction, skip adding the input +// // altogether. +// if avaxBalance <= additionalFee { +// continue +// } + +// // Update the cost for the next iteration +// cost = newCost + +// amountToConsume, err = math.Add64(amountToConsume, additionalFee) +// if err != nil { +// return nil, err +// } + +// nonce, err := b.backend.Nonce(ctx, addr) +// if err != nil { +// return nil, err +// } + +// inputAmount := math.Min(amountToConsume, avaxBalance) +// inputs = append(inputs, evm.EVMInput{ +// Address: addr, +// Amount: inputAmount, +// AssetID: avaxAssetID, +// Nonce: nonce, +// }) +// amountToConsume -= inputAmount +// } + +// if amountToConsume > 0 { +// return nil, errInsufficientFunds +// } + +// utils.Sort(inputs) +// tx.Ins = inputs +// return tx, nil +// } + +// func getSpendableAmount( +// utxo *avax.UTXO, +// addrs set.Set[ids.ShortID], +// minIssuanceTime uint64, +// avaxAssetID ids.ID, +// ) (uint64, []uint32, bool) { +// if utxo.Asset.ID != avaxAssetID { +// // Only AVAX can be imported +// return 0, nil, false +// } + +// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) +// if !ok { +// // Can't import an unknown transfer output type +// return 0, nil, false +// } + +// inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) +// return out.Amt, inputSigIndices, ok +// } diff --git a/wallet/chain/c/builder_with_options.go b/wallet/chain/c/builder_with_options.go index 8416dddf9928..9b7ab8399484 100644 --- a/wallet/chain/c/builder_with_options.go +++ b/wallet/chain/c/builder_with_options.go @@ -3,81 +3,81 @@ package c -import ( - "math/big" +// import ( +// "math/big" - "github.com/ava-labs/coreth/plugin/evm" +// "github.com/ava-labs/coreth/plugin/evm" - ethcommon "github.com/ethereum/go-ethereum/common" +// ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) -var _ Builder = (*builderWithOptions)(nil) +// var _ Builder = (*builderWithOptions)(nil) -type builderWithOptions struct { - Builder - options []common.Option -} +// type builderWithOptions struct { +// Builder +// options []common.Option +// } -// NewBuilderWithOptions returns a new transaction builder that will use the -// given options by default. -// -// - [builder] is the builder that will be called to perform the underlying -// operations. -// - [options] will be provided to the builder in addition to the options -// provided in the method calls. -func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { - return &builderWithOptions{ - Builder: builder, - options: options, - } -} +// // NewBuilderWithOptions returns a new transaction builder that will use the +// // given options by default. +// // +// // - [builder] is the builder that will be called to perform the underlying +// // operations. +// // - [options] will be provided to the builder in addition to the options +// // provided in the method calls. +// func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { +// return &builderWithOptions{ +// Builder: builder, +// options: options, +// } +// } -func (b *builderWithOptions) GetBalance( - options ...common.Option, -) (*big.Int, error) { - return b.Builder.GetBalance( - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) GetBalance( +// options ...common.Option, +// ) (*big.Int, error) { +// return b.Builder.GetBalance( +// common.UnionOptions(b.options, options)..., +// ) +// } -func (b *builderWithOptions) GetImportableBalance( - chainID ids.ID, - options ...common.Option, -) (uint64, error) { - return b.Builder.GetImportableBalance( - chainID, - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) GetImportableBalance( +// chainID ids.ID, +// options ...common.Option, +// ) (uint64, error) { +// return b.Builder.GetImportableBalance( +// chainID, +// common.UnionOptions(b.options, options)..., +// ) +// } -func (b *builderWithOptions) NewImportTx( - chainID ids.ID, - to ethcommon.Address, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedImportTx, error) { - return b.Builder.NewImportTx( - chainID, - to, - baseFee, - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) NewImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedImportTx, error) { +// return b.Builder.NewImportTx( +// chainID, +// to, +// baseFee, +// common.UnionOptions(b.options, options)..., +// ) +// } -func (b *builderWithOptions) NewExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedExportTx, error) { - return b.Builder.NewExportTx( - chainID, - outputs, - baseFee, - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) NewExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedExportTx, error) { +// return b.Builder.NewExportTx( +// chainID, +// outputs, +// baseFee, +// common.UnionOptions(b.options, options)..., +// ) +// } diff --git a/wallet/chain/c/context.go b/wallet/chain/c/context.go index d506b42f81fa..1c01d8fb55c8 100644 --- a/wallet/chain/c/context.go +++ b/wallet/chain/c/context.go @@ -3,81 +3,81 @@ package c -import ( - stdcontext "context" +// import ( +// stdcontext "context" - "github.com/ava-labs/avalanchego/api/info" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/avm" -) +// "github.com/ava-labs/avalanchego/api/info" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/avm" +// ) -var _ Context = (*context)(nil) +// var _ Context = (*context)(nil) -type Context interface { - NetworkID() uint32 - BlockchainID() ids.ID - AVAXAssetID() ids.ID -} +// type Context interface { +// NetworkID() uint32 +// BlockchainID() ids.ID +// AVAXAssetID() ids.ID +// } -type context struct { - networkID uint32 - blockchainID ids.ID - avaxAssetID ids.ID -} +// type context struct { +// networkID uint32 +// blockchainID ids.ID +// avaxAssetID ids.ID +// } -func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { - infoClient := info.NewClient(uri) - xChainClient := avm.NewClient(uri, "X") - return NewContextFromClients(ctx, infoClient, xChainClient) -} +// func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { +// infoClient := info.NewClient(uri) +// xChainClient := avm.NewClient(uri, "X") +// return NewContextFromClients(ctx, infoClient, xChainClient) +// } -func NewContextFromClients( - ctx stdcontext.Context, - infoClient info.Client, - xChainClient avm.Client, -) (Context, error) { - networkID, err := infoClient.GetNetworkID(ctx) - if err != nil { - return nil, err - } +// func NewContextFromClients( +// ctx stdcontext.Context, +// infoClient info.Client, +// xChainClient avm.Client, +// ) (Context, error) { +// networkID, err := infoClient.GetNetworkID(ctx) +// if err != nil { +// return nil, err +// } - chainID, err := infoClient.GetBlockchainID(ctx, "C") - if err != nil { - return nil, err - } +// chainID, err := infoClient.GetBlockchainID(ctx, "C") +// if err != nil { +// return nil, err +// } - asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") - if err != nil { - return nil, err - } +// asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") +// if err != nil { +// return nil, err +// } - return NewContext( - networkID, - chainID, - asset.AssetID, - ), nil -} +// return NewContext( +// networkID, +// chainID, +// asset.AssetID, +// ), nil +// } -func NewContext( - networkID uint32, - blockchainID ids.ID, - avaxAssetID ids.ID, -) Context { - return &context{ - networkID: networkID, - blockchainID: blockchainID, - avaxAssetID: avaxAssetID, - } -} +// func NewContext( +// networkID uint32, +// blockchainID ids.ID, +// avaxAssetID ids.ID, +// ) Context { +// return &context{ +// networkID: networkID, +// blockchainID: blockchainID, +// avaxAssetID: avaxAssetID, +// } +// } -func (c *context) NetworkID() uint32 { - return c.networkID -} +// func (c *context) NetworkID() uint32 { +// return c.networkID +// } -func (c *context) BlockchainID() ids.ID { - return c.blockchainID -} +// func (c *context) BlockchainID() ids.ID { +// return c.blockchainID +// } -func (c *context) AVAXAssetID() ids.ID { - return c.avaxAssetID -} +// func (c *context) AVAXAssetID() ids.ID { +// return c.avaxAssetID +// } diff --git a/wallet/chain/c/signer.go b/wallet/chain/c/signer.go index 4fd85ed3b532..4bedc378234b 100644 --- a/wallet/chain/c/signer.go +++ b/wallet/chain/c/signer.go @@ -3,221 +3,221 @@ package c -import ( - "errors" - "fmt" - - stdcontext "context" - - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/crypto/keychain" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/hashing" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/components/verify" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" -) - -const version = 0 - -var ( - _ Signer = (*txSigner)(nil) - - errUnknownInputType = errors.New("unknown input type") - errUnknownCredentialType = errors.New("unknown credential type") - errUnknownOutputType = errors.New("unknown output type") - errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") - - emptySig [secp256k1.SignatureLen]byte -) - -type Signer interface { - SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) - SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error -} - -type EthKeychain interface { - // The returned Signer can provide a signature for [addr] - GetEth(addr ethcommon.Address) (keychain.Signer, bool) - // Returns the set of addresses for which the accessor keeps an associated - // signer - EthAddresses() set.Set[ethcommon.Address] -} - -type SignerBackend interface { - GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) -} - -type txSigner struct { - avaxKC keychain.Keychain - ethKC EthKeychain - backend SignerBackend -} - -func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { - return &txSigner{ - avaxKC: avaxKC, - ethKC: ethKC, - backend: backend, - } -} - -func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { - tx := &evm.Tx{UnsignedAtomicTx: utx} - return tx, s.SignAtomic(ctx, tx) -} - -func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { - switch utx := tx.UnsignedAtomicTx.(type) { - case *evm.UnsignedImportTx: - signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) - if err != nil { - return err - } - return sign(tx, true, signers) - case *evm.UnsignedExportTx: - signers := s.getExportSigners(utx.Ins) - return sign(tx, true, signers) - default: - return fmt.Errorf("%w: %T", errUnknownTxType, tx) - } -} - -func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { - txSigners := make([][]keychain.Signer, len(ins)) - for credIndex, transferInput := range ins { - input, ok := transferInput.In.(*secp256k1fx.TransferInput) - if !ok { - return nil, errUnknownInputType - } - - inputSigners := make([]keychain.Signer, len(input.SigIndices)) - txSigners[credIndex] = inputSigners - - utxoID := transferInput.InputID() - utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) - if err == database.ErrNotFound { - // If we don't have access to the UTXO, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - if err != nil { - return nil, err - } - - out, ok := utxo.Out.(*secp256k1fx.TransferOutput) - if !ok { - return nil, errUnknownOutputType - } - - for sigIndex, addrIndex := range input.SigIndices { - if addrIndex >= uint32(len(out.Addrs)) { - return nil, errInvalidUTXOSigIndex - } - - addr := out.Addrs[addrIndex] - key, ok := s.avaxKC.Get(addr) - if !ok { - // If we don't have access to the key, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - inputSigners[sigIndex] = key - } - } - return txSigners, nil -} - -func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { - txSigners := make([][]keychain.Signer, len(ins)) - for credIndex, input := range ins { - inputSigners := make([]keychain.Signer, 1) - txSigners[credIndex] = inputSigners - - key, ok := s.ethKC.GetEth(input.Address) - if !ok { - // If we don't have access to the key, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - inputSigners[0] = key - } - return txSigners -} - -// TODO: remove [signHash] after the ledger supports signing all transactions. -func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { - unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) - if err != nil { - return fmt.Errorf("couldn't marshal unsigned tx: %w", err) - } - unsignedHash := hashing.ComputeHash256(unsignedBytes) - - if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { - tx.Creds = make([]verify.Verifiable, expectedLen) - } - - sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) - for credIndex, inputSigners := range txSigners { - credIntf := tx.Creds[credIndex] - if credIntf == nil { - credIntf = &secp256k1fx.Credential{} - tx.Creds[credIndex] = credIntf - } - - cred, ok := credIntf.(*secp256k1fx.Credential) - if !ok { - return errUnknownCredentialType - } - if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { - cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) - } - - for sigIndex, signer := range inputSigners { - if signer == nil { - // If we don't have access to the key, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - addr := signer.Address() - if sig := cred.Sigs[sigIndex]; sig != emptySig { - // If this signature has already been populated, we can just - // copy the needed signature for the future. - sigCache[addr] = sig - continue - } - - if sig, exists := sigCache[addr]; exists { - // If this key has already produced a signature, we can just - // copy the previous signature. - cred.Sigs[sigIndex] = sig - continue - } - - var sig []byte - if signHash { - sig, err = signer.SignHash(unsignedHash) - } else { - sig, err = signer.Sign(unsignedBytes) - } - if err != nil { - return fmt.Errorf("problem signing tx: %w", err) - } - copy(cred.Sigs[sigIndex][:], sig) - sigCache[addr] = cred.Sigs[sigIndex] - } - } - - signedBytes, err := evm.Codec.Marshal(version, tx) - if err != nil { - return fmt.Errorf("couldn't marshal tx: %w", err) - } - tx.Initialize(unsignedBytes, signedBytes) - return nil -} +// import ( +// "errors" +// "fmt" + +// stdcontext "context" + +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/database" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils/crypto/keychain" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/hashing" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/components/verify" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// ) + +// const version = 0 + +// var ( +// _ Signer = (*txSigner)(nil) + +// errUnknownInputType = errors.New("unknown input type") +// errUnknownCredentialType = errors.New("unknown credential type") +// errUnknownOutputType = errors.New("unknown output type") +// errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") + +// emptySig [secp256k1.SignatureLen]byte +// ) + +// type Signer interface { +// SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) +// SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error +// } + +// type EthKeychain interface { +// // The returned Signer can provide a signature for [addr] +// GetEth(addr ethcommon.Address) (keychain.Signer, bool) +// // Returns the set of addresses for which the accessor keeps an associated +// // signer +// EthAddresses() set.Set[ethcommon.Address] +// } + +// type SignerBackend interface { +// GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) +// } + +// type txSigner struct { +// avaxKC keychain.Keychain +// ethKC EthKeychain +// backend SignerBackend +// } + +// func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { +// return &txSigner{ +// avaxKC: avaxKC, +// ethKC: ethKC, +// backend: backend, +// } +// } + +// func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { +// tx := &evm.Tx{UnsignedAtomicTx: utx} +// return tx, s.SignAtomic(ctx, tx) +// } + +// func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { +// switch utx := tx.UnsignedAtomicTx.(type) { +// case *evm.UnsignedImportTx: +// signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) +// if err != nil { +// return err +// } +// return sign(tx, true, signers) +// case *evm.UnsignedExportTx: +// signers := s.getExportSigners(utx.Ins) +// return sign(tx, true, signers) +// default: +// return fmt.Errorf("%w: %T", errUnknownTxType, tx) +// } +// } + +// func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { +// txSigners := make([][]keychain.Signer, len(ins)) +// for credIndex, transferInput := range ins { +// input, ok := transferInput.In.(*secp256k1fx.TransferInput) +// if !ok { +// return nil, errUnknownInputType +// } + +// inputSigners := make([]keychain.Signer, len(input.SigIndices)) +// txSigners[credIndex] = inputSigners + +// utxoID := transferInput.InputID() +// utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) +// if err == database.ErrNotFound { +// // If we don't have access to the UTXO, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// if err != nil { +// return nil, err +// } + +// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) +// if !ok { +// return nil, errUnknownOutputType +// } + +// for sigIndex, addrIndex := range input.SigIndices { +// if addrIndex >= uint32(len(out.Addrs)) { +// return nil, errInvalidUTXOSigIndex +// } + +// addr := out.Addrs[addrIndex] +// key, ok := s.avaxKC.Get(addr) +// if !ok { +// // If we don't have access to the key, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// inputSigners[sigIndex] = key +// } +// } +// return txSigners, nil +// } + +// func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { +// txSigners := make([][]keychain.Signer, len(ins)) +// for credIndex, input := range ins { +// inputSigners := make([]keychain.Signer, 1) +// txSigners[credIndex] = inputSigners + +// key, ok := s.ethKC.GetEth(input.Address) +// if !ok { +// // If we don't have access to the key, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// inputSigners[0] = key +// } +// return txSigners +// } + +// // TODO: remove [signHash] after the ledger supports signing all transactions. +// func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { +// unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) +// if err != nil { +// return fmt.Errorf("couldn't marshal unsigned tx: %w", err) +// } +// unsignedHash := hashing.ComputeHash256(unsignedBytes) + +// if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { +// tx.Creds = make([]verify.Verifiable, expectedLen) +// } + +// sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) +// for credIndex, inputSigners := range txSigners { +// credIntf := tx.Creds[credIndex] +// if credIntf == nil { +// credIntf = &secp256k1fx.Credential{} +// tx.Creds[credIndex] = credIntf +// } + +// cred, ok := credIntf.(*secp256k1fx.Credential) +// if !ok { +// return errUnknownCredentialType +// } +// if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { +// cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) +// } + +// for sigIndex, signer := range inputSigners { +// if signer == nil { +// // If we don't have access to the key, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// addr := signer.Address() +// if sig := cred.Sigs[sigIndex]; sig != emptySig { +// // If this signature has already been populated, we can just +// // copy the needed signature for the future. +// sigCache[addr] = sig +// continue +// } + +// if sig, exists := sigCache[addr]; exists { +// // If this key has already produced a signature, we can just +// // copy the previous signature. +// cred.Sigs[sigIndex] = sig +// continue +// } + +// var sig []byte +// if signHash { +// sig, err = signer.SignHash(unsignedHash) +// } else { +// sig, err = signer.Sign(unsignedBytes) +// } +// if err != nil { +// return fmt.Errorf("problem signing tx: %w", err) +// } +// copy(cred.Sigs[sigIndex][:], sig) +// sigCache[addr] = cred.Sigs[sigIndex] +// } +// } + +// signedBytes, err := evm.Codec.Marshal(version, tx) +// if err != nil { +// return fmt.Errorf("couldn't marshal tx: %w", err) +// } +// tx.Initialize(unsignedBytes, signedBytes) +// return nil +// } diff --git a/wallet/chain/c/wallet.go b/wallet/chain/c/wallet.go index fb1a83d53dad..ebee50a9a958 100644 --- a/wallet/chain/c/wallet.go +++ b/wallet/chain/c/wallet.go @@ -3,204 +3,204 @@ package c -import ( - "errors" - "math/big" - "time" - - "github.com/ava-labs/coreth/ethclient" - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var ( - _ Wallet = (*wallet)(nil) - - errNotCommitted = errors.New("not committed") -) - -type Wallet interface { - Context - - // Builder returns the builder that will be used to create the transactions. - Builder() Builder - - // Signer returns the signer that will be used to sign the transactions. - Signer() Signer - - // IssueImportTx creates, signs, and issues an import transaction that - // attempts to consume all the available UTXOs and import the funds to [to]. - // - // - [chainID] specifies the chain to be importing funds from. - // - [to] specifies where to send the imported funds to. - IssueImportTx( - chainID ids.ID, - to ethcommon.Address, - options ...common.Option, - ) (*evm.Tx, error) - - // IssueExportTx creates, signs, and issues an export transaction that - // attempts to send all the provided [outputs] to the requested [chainID]. - // - // - [chainID] specifies the chain to be exporting the funds to. - // - [outputs] specifies the outputs to send to the [chainID]. - IssueExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - options ...common.Option, - ) (*evm.Tx, error) - - // IssueUnsignedTx signs and issues the unsigned tx. - IssueUnsignedAtomicTx( - utx evm.UnsignedAtomicTx, - options ...common.Option, - ) (*evm.Tx, error) - - // IssueAtomicTx issues the signed tx. - IssueAtomicTx( - tx *evm.Tx, - options ...common.Option, - ) error -} - -func NewWallet( - builder Builder, - signer Signer, - avaxClient evm.Client, - ethClient ethclient.Client, - backend Backend, -) Wallet { - return &wallet{ - Backend: backend, - builder: builder, - signer: signer, - avaxClient: avaxClient, - ethClient: ethClient, - } -} - -type wallet struct { - Backend - builder Builder - signer Signer - avaxClient evm.Client - ethClient ethclient.Client -} - -func (w *wallet) Builder() Builder { - return w.builder -} - -func (w *wallet) Signer() Signer { - return w.signer -} - -func (w *wallet) IssueImportTx( - chainID ids.ID, - to ethcommon.Address, - options ...common.Option, -) (*evm.Tx, error) { - baseFee, err := w.baseFee(options) - if err != nil { - return nil, err - } - - utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) - if err != nil { - return nil, err - } - return w.IssueUnsignedAtomicTx(utx, options...) -} - -func (w *wallet) IssueExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - options ...common.Option, -) (*evm.Tx, error) { - baseFee, err := w.baseFee(options) - if err != nil { - return nil, err - } - - utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) - if err != nil { - return nil, err - } - return w.IssueUnsignedAtomicTx(utx, options...) -} - -func (w *wallet) IssueUnsignedAtomicTx( - utx evm.UnsignedAtomicTx, - options ...common.Option, -) (*evm.Tx, error) { - ops := common.NewOptions(options) - ctx := ops.Context() - tx, err := w.signer.SignUnsignedAtomic(ctx, utx) - if err != nil { - return nil, err - } - - return tx, w.IssueAtomicTx(tx, options...) -} - -func (w *wallet) IssueAtomicTx( - tx *evm.Tx, - options ...common.Option, -) error { - ops := common.NewOptions(options) - ctx := ops.Context() - txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) - if err != nil { - return err - } - - if f := ops.PostIssuanceFunc(); f != nil { - f(txID) - } - - if ops.AssumeDecided() { - return w.Backend.AcceptAtomicTx(ctx, tx) - } - - pollFrequency := ops.PollFrequency() - ticker := time.NewTicker(pollFrequency) - defer ticker.Stop() - - for { - status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) - if err != nil { - return err - } - - switch status { - case evm.Accepted: - return w.Backend.AcceptAtomicTx(ctx, tx) - case evm.Dropped, evm.Unknown: - return errNotCommitted - } - - // The tx is Processing. - - select { - case <-ticker.C: - case <-ctx.Done(): - return ctx.Err() - } - } -} - -func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { - ops := common.NewOptions(options) - baseFee := ops.BaseFee(nil) - if baseFee != nil { - return baseFee, nil - } - - ctx := ops.Context() - return w.ethClient.EstimateBaseFee(ctx) -} +// import ( +// "errors" +// "math/big" +// "time" + +// "github.com/ava-labs/coreth/ethclient" +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var ( +// _ Wallet = (*wallet)(nil) + +// errNotCommitted = errors.New("not committed") +// ) + +// type Wallet interface { +// Context + +// // Builder returns the builder that will be used to create the transactions. +// Builder() Builder + +// // Signer returns the signer that will be used to sign the transactions. +// Signer() Signer + +// // IssueImportTx creates, signs, and issues an import transaction that +// // attempts to consume all the available UTXOs and import the funds to [to]. +// // +// // - [chainID] specifies the chain to be importing funds from. +// // - [to] specifies where to send the imported funds to. +// IssueImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// options ...common.Option, +// ) (*evm.Tx, error) + +// // IssueExportTx creates, signs, and issues an export transaction that +// // attempts to send all the provided [outputs] to the requested [chainID]. +// // +// // - [chainID] specifies the chain to be exporting the funds to. +// // - [outputs] specifies the outputs to send to the [chainID]. +// IssueExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// options ...common.Option, +// ) (*evm.Tx, error) + +// // IssueUnsignedTx signs and issues the unsigned tx. +// IssueUnsignedAtomicTx( +// utx evm.UnsignedAtomicTx, +// options ...common.Option, +// ) (*evm.Tx, error) + +// // IssueAtomicTx issues the signed tx. +// IssueAtomicTx( +// tx *evm.Tx, +// options ...common.Option, +// ) error +// } + +// func NewWallet( +// builder Builder, +// signer Signer, +// avaxClient evm.Client, +// ethClient ethclient.Client, +// backend Backend, +// ) Wallet { +// return &wallet{ +// Backend: backend, +// builder: builder, +// signer: signer, +// avaxClient: avaxClient, +// ethClient: ethClient, +// } +// } + +// type wallet struct { +// Backend +// builder Builder +// signer Signer +// avaxClient evm.Client +// ethClient ethclient.Client +// } + +// func (w *wallet) Builder() Builder { +// return w.builder +// } + +// func (w *wallet) Signer() Signer { +// return w.signer +// } + +// func (w *wallet) IssueImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// options ...common.Option, +// ) (*evm.Tx, error) { +// baseFee, err := w.baseFee(options) +// if err != nil { +// return nil, err +// } + +// utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) +// if err != nil { +// return nil, err +// } +// return w.IssueUnsignedAtomicTx(utx, options...) +// } + +// func (w *wallet) IssueExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// options ...common.Option, +// ) (*evm.Tx, error) { +// baseFee, err := w.baseFee(options) +// if err != nil { +// return nil, err +// } + +// utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) +// if err != nil { +// return nil, err +// } +// return w.IssueUnsignedAtomicTx(utx, options...) +// } + +// func (w *wallet) IssueUnsignedAtomicTx( +// utx evm.UnsignedAtomicTx, +// options ...common.Option, +// ) (*evm.Tx, error) { +// ops := common.NewOptions(options) +// ctx := ops.Context() +// tx, err := w.signer.SignUnsignedAtomic(ctx, utx) +// if err != nil { +// return nil, err +// } + +// return tx, w.IssueAtomicTx(tx, options...) +// } + +// func (w *wallet) IssueAtomicTx( +// tx *evm.Tx, +// options ...common.Option, +// ) error { +// ops := common.NewOptions(options) +// ctx := ops.Context() +// txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) +// if err != nil { +// return err +// } + +// if f := ops.PostIssuanceFunc(); f != nil { +// f(txID) +// } + +// if ops.AssumeDecided() { +// return w.Backend.AcceptAtomicTx(ctx, tx) +// } + +// pollFrequency := ops.PollFrequency() +// ticker := time.NewTicker(pollFrequency) +// defer ticker.Stop() + +// for { +// status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) +// if err != nil { +// return err +// } + +// switch status { +// case evm.Accepted: +// return w.Backend.AcceptAtomicTx(ctx, tx) +// case evm.Dropped, evm.Unknown: +// return errNotCommitted +// } + +// // The tx is Processing. + +// select { +// case <-ticker.C: +// case <-ctx.Done(): +// return ctx.Err() +// } +// } +// } + +// func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { +// ops := common.NewOptions(options) +// baseFee := ops.BaseFee(nil) +// if baseFee != nil { +// return baseFee, nil +// } + +// ctx := ops.Context() +// return w.ethClient.EstimateBaseFee(ctx) +// } diff --git a/wallet/chain/c/wallet_with_options.go b/wallet/chain/c/wallet_with_options.go index 7d6193683d49..fd69a6d4fd02 100644 --- a/wallet/chain/c/wallet_with_options.go +++ b/wallet/chain/c/wallet_with_options.go @@ -3,80 +3,80 @@ package c -import ( - "github.com/ava-labs/coreth/plugin/evm" +// import ( +// "github.com/ava-labs/coreth/plugin/evm" - ethcommon "github.com/ethereum/go-ethereum/common" +// ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) -var _ Wallet = (*walletWithOptions)(nil) +// var _ Wallet = (*walletWithOptions)(nil) -func NewWalletWithOptions( - wallet Wallet, - options ...common.Option, -) Wallet { - return &walletWithOptions{ - Wallet: wallet, - options: options, - } -} +// func NewWalletWithOptions( +// wallet Wallet, +// options ...common.Option, +// ) Wallet { +// return &walletWithOptions{ +// Wallet: wallet, +// options: options, +// } +// } -type walletWithOptions struct { - Wallet - options []common.Option -} +// type walletWithOptions struct { +// Wallet +// options []common.Option +// } -func (w *walletWithOptions) Builder() Builder { - return NewBuilderWithOptions( - w.Wallet.Builder(), - w.options..., - ) -} +// func (w *walletWithOptions) Builder() Builder { +// return NewBuilderWithOptions( +// w.Wallet.Builder(), +// w.options..., +// ) +// } -func (w *walletWithOptions) IssueImportTx( - chainID ids.ID, - to ethcommon.Address, - options ...common.Option, -) (*evm.Tx, error) { - return w.Wallet.IssueImportTx( - chainID, - to, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// options ...common.Option, +// ) (*evm.Tx, error) { +// return w.Wallet.IssueImportTx( +// chainID, +// to, +// common.UnionOptions(w.options, options)..., +// ) +// } -func (w *walletWithOptions) IssueExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - options ...common.Option, -) (*evm.Tx, error) { - return w.Wallet.IssueExportTx( - chainID, - outputs, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// options ...common.Option, +// ) (*evm.Tx, error) { +// return w.Wallet.IssueExportTx( +// chainID, +// outputs, +// common.UnionOptions(w.options, options)..., +// ) +// } -func (w *walletWithOptions) IssueUnsignedAtomicTx( - utx evm.UnsignedAtomicTx, - options ...common.Option, -) (*evm.Tx, error) { - return w.Wallet.IssueUnsignedAtomicTx( - utx, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueUnsignedAtomicTx( +// utx evm.UnsignedAtomicTx, +// options ...common.Option, +// ) (*evm.Tx, error) { +// return w.Wallet.IssueUnsignedAtomicTx( +// utx, +// common.UnionOptions(w.options, options)..., +// ) +// } -func (w *walletWithOptions) IssueAtomicTx( - tx *evm.Tx, - options ...common.Option, -) error { - return w.Wallet.IssueAtomicTx( - tx, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueAtomicTx( +// tx *evm.Tx, +// options ...common.Option, +// ) error { +// return w.Wallet.IssueAtomicTx( +// tx, +// common.UnionOptions(w.options, options)..., +// ) +// } diff --git a/wallet/subnet/primary/api.go b/wallet/subnet/primary/api.go index 3ac72c217884..3260c05a0a1b 100644 --- a/wallet/subnet/primary/api.go +++ b/wallet/subnet/primary/api.go @@ -5,12 +5,6 @@ package primary import ( "context" - "fmt" - - "github.com/ava-labs/coreth/ethclient" - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ethereum/go-ethereum/common" "github.com/ava-labs/avalanchego/api/info" "github.com/ava-labs/avalanchego/codec" @@ -22,7 +16,6 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm" "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" ) @@ -59,9 +52,9 @@ type AVAXState struct { PCTX p.Context XClient avm.Client XCTX x.Context - CClient evm.Client - CCTX c.Context - UTXOs UTXOs + // CClient evm.Client + // CCTX c.Context + UTXOs UTXOs } func FetchState( @@ -75,7 +68,7 @@ func FetchState( infoClient := info.NewClient(uri) pClient := platformvm.NewClient(uri) xClient := avm.NewClient(uri, "X") - cClient := evm.NewCChainClient(uri) + // cClient := evm.NewCChainClient(uri) pCTX, err := p.NewContextFromClients(ctx, infoClient, xClient) if err != nil { @@ -87,10 +80,10 @@ func FetchState( return nil, err } - cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) - if err != nil { - return nil, err - } + // cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) + // if err != nil { + // return nil, err + // } utxos := NewUTXOs() addrList := addrs.List() @@ -109,11 +102,11 @@ func FetchState( client: xClient, codec: x.Parser.Codec(), }, - { - id: cCTX.BlockchainID(), - client: cClient, - codec: evm.Codec, - }, + // { + // id: cCTX.BlockchainID(), + // client: cClient, + // codec: evm.Codec, + // }, } for _, destinationChain := range chains { for _, sourceChain := range chains { @@ -136,52 +129,52 @@ func FetchState( PCTX: pCTX, XClient: xClient, XCTX: xCTX, - CClient: cClient, - CCTX: cCTX, - UTXOs: utxos, + // CClient: cClient, + // CCTX: cCTX, + UTXOs: utxos, }, nil } -type EthState struct { - Client ethclient.Client - Accounts map[common.Address]*c.Account -} - -func FetchEthState( - ctx context.Context, - uri string, - addrs set.Set[common.Address], -) (*EthState, error) { - path := fmt.Sprintf( - "%s/ext/%s/C/rpc", - uri, - constants.ChainAliasPrefix, - ) - client, err := ethclient.Dial(path) - if err != nil { - return nil, err - } - - accounts := make(map[common.Address]*c.Account, addrs.Len()) - for addr := range addrs { - balance, err := client.BalanceAt(ctx, addr, nil) - if err != nil { - return nil, err - } - nonce, err := client.NonceAt(ctx, addr, nil) - if err != nil { - return nil, err - } - accounts[addr] = &c.Account{ - Balance: balance, - Nonce: nonce, - } - } - return &EthState{ - Client: client, - Accounts: accounts, - }, nil -} +// type EthState struct { +// Client ethclient.Client +// Accounts map[common.Address]*c.Account +// } + +// func FetchEthState( +// ctx context.Context, +// uri string, +// addrs set.Set[common.Address], +// ) (*EthState, error) { +// path := fmt.Sprintf( +// "%s/ext/%s/C/rpc", +// uri, +// constants.ChainAliasPrefix, +// ) +// client, err := ethclient.Dial(path) +// if err != nil { +// return nil, err +// } + +// accounts := make(map[common.Address]*c.Account, addrs.Len()) +// for addr := range addrs { +// balance, err := client.BalanceAt(ctx, addr, nil) +// if err != nil { +// return nil, err +// } +// nonce, err := client.NonceAt(ctx, addr, nil) +// if err != nil { +// return nil, err +// } +// accounts[addr] = &c.Account{ +// Balance: balance, +// Nonce: nonce, +// } +// } +// return &EthState{ +// Client: client, +// Accounts: accounts, +// }, nil +// } // AddAllUTXOs fetches all the UTXOs referenced by [addresses] that were sent // from [sourceChainID] to [destinationChainID] from the [client]. It then uses diff --git a/wallet/subnet/primary/example_test.go b/wallet/subnet/primary/example_test.go index 483c049d4ac0..4a73e8c070b2 100644 --- a/wallet/subnet/primary/example_test.go +++ b/wallet/subnet/primary/example_test.go @@ -30,7 +30,7 @@ func ExampleWallet() { wallet, err := MakeWallet(ctx, &WalletConfig{ URI: LocalAPIURI, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet with: %s\n", err) diff --git a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go index d5e8ce422307..21c081d2982b 100644 --- a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go @@ -46,9 +46,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/add-primary-validator/main.go b/wallet/subnet/primary/examples/add-primary-validator/main.go index a56dae23db3a..13c28f995f63 100644 --- a/wallet/subnet/primary/examples/add-primary-validator/main.go +++ b/wallet/subnet/primary/examples/add-primary-validator/main.go @@ -45,7 +45,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/c-chain-export/main.go b/wallet/subnet/primary/examples/c-chain-export/main.go index fec55c899feb..a6b9a0c810b8 100644 --- a/wallet/subnet/primary/examples/c-chain-export/main.go +++ b/wallet/subnet/primary/examples/c-chain-export/main.go @@ -3,70 +3,70 @@ package main -import ( - "context" - "log" - "time" +// import ( +// "context" +// "log" +// "time" - "github.com/ava-labs/avalanchego/genesis" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary" -) +// "github.com/ava-labs/avalanchego/genesis" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary" +// ) -func main() { - key := genesis.EWOQKey - uri := primary.LocalAPIURI - kc := secp256k1fx.NewKeychain(key) - avaxAddr := key.Address() +// func main() { +// key := genesis.EWOQKey +// uri := primary.LocalAPIURI +// kc := secp256k1fx.NewKeychain(key) +// avaxAddr := key.Address() - ctx := context.Background() +// ctx := context.Background() - // MakeWallet fetches the available UTXOs owned by [kc] on the network that - // [uri] is hosting. - walletSyncStartTime := time.Now() - wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, - }) - if err != nil { - log.Fatalf("failed to initialize wallet: %s\n", err) - } - log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) +// // MakeWallet fetches the available UTXOs owned by [kc] on the network that +// // [uri] is hosting. +// walletSyncStartTime := time.Now() +// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ +// URI: uri, +// AVAXKeychain: kc, +// EthKeychain: kc, +// }) +// if err != nil { +// log.Fatalf("failed to initialize wallet: %s\n", err) +// } +// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) - // Get the P-chain wallet - pWallet := wallet.P() - cWallet := wallet.C() +// // Get the P-chain wallet +// pWallet := wallet.P() +// cWallet := wallet.C() - // Pull out useful constants to use when issuing transactions. - cChainID := cWallet.BlockchainID() - owner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - avaxAddr, - }, - } +// // Pull out useful constants to use when issuing transactions. +// cChainID := cWallet.BlockchainID() +// owner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// avaxAddr, +// }, +// } - exportStartTime := time.Now() - exportTx, err := cWallet.IssueExportTx( - constants.PlatformChainID, - []*secp256k1fx.TransferOutput{{ - Amt: units.Avax, - OutputOwners: owner, - }}, - ) - if err != nil { - log.Fatalf("failed to issue export transaction: %s\n", err) - } - log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) +// exportStartTime := time.Now() +// exportTx, err := cWallet.IssueExportTx( +// constants.PlatformChainID, +// []*secp256k1fx.TransferOutput{{ +// Amt: units.Avax, +// OutputOwners: owner, +// }}, +// ) +// if err != nil { +// log.Fatalf("failed to issue export transaction: %s\n", err) +// } +// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) - importStartTime := time.Now() - importTx, err := pWallet.IssueImportTx(cChainID, &owner) - if err != nil { - log.Fatalf("failed to issue import transaction: %s\n", err) - } - log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) -} +// importStartTime := time.Now() +// importTx, err := pWallet.IssueImportTx(cChainID, &owner) +// if err != nil { +// log.Fatalf("failed to issue import transaction: %s\n", err) +// } +// log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) +// } diff --git a/wallet/subnet/primary/examples/c-chain-import/main.go b/wallet/subnet/primary/examples/c-chain-import/main.go index b4dc4e603eb3..2d9b8a244cb0 100644 --- a/wallet/subnet/primary/examples/c-chain-import/main.go +++ b/wallet/subnet/primary/examples/c-chain-import/main.go @@ -3,75 +3,75 @@ package main -import ( - "context" - "log" - "time" +// import ( +// "context" +// "log" +// "time" - "github.com/ava-labs/coreth/plugin/evm" +// "github.com/ava-labs/coreth/plugin/evm" - "github.com/ava-labs/avalanchego/genesis" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary" -) +// "github.com/ava-labs/avalanchego/genesis" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary" +// ) -func main() { - key := genesis.EWOQKey - uri := primary.LocalAPIURI - kc := secp256k1fx.NewKeychain(key) - avaxAddr := key.Address() - ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) +// func main() { +// key := genesis.EWOQKey +// uri := primary.LocalAPIURI +// kc := secp256k1fx.NewKeychain(key) +// avaxAddr := key.Address() +// ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) - ctx := context.Background() +// ctx := context.Background() - // MakeWallet fetches the available UTXOs owned by [kc] on the network that - // [uri] is hosting. - walletSyncStartTime := time.Now() - wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, - }) - if err != nil { - log.Fatalf("failed to initialize wallet: %s\n", err) - } - log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) +// // MakeWallet fetches the available UTXOs owned by [kc] on the network that +// // [uri] is hosting. +// walletSyncStartTime := time.Now() +// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ +// URI: uri, +// AVAXKeychain: kc, +// EthKeychain: kc, +// }) +// if err != nil { +// log.Fatalf("failed to initialize wallet: %s\n", err) +// } +// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) - // Get the P-chain wallet - pWallet := wallet.P() - cWallet := wallet.C() +// // Get the P-chain wallet +// pWallet := wallet.P() +// cWallet := wallet.C() - // Pull out useful constants to use when issuing transactions. - cChainID := cWallet.BlockchainID() - avaxAssetID := cWallet.AVAXAssetID() - owner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - avaxAddr, - }, - } +// // Pull out useful constants to use when issuing transactions. +// cChainID := cWallet.BlockchainID() +// avaxAssetID := cWallet.AVAXAssetID() +// owner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// avaxAddr, +// }, +// } - exportStartTime := time.Now() - exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ - Asset: avax.Asset{ID: avaxAssetID}, - Out: &secp256k1fx.TransferOutput{ - Amt: units.Avax, - OutputOwners: owner, - }, - }}) - if err != nil { - log.Fatalf("failed to issue export transaction: %s\n", err) - } - log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) +// exportStartTime := time.Now() +// exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ +// Asset: avax.Asset{ID: avaxAssetID}, +// Out: &secp256k1fx.TransferOutput{ +// Amt: units.Avax, +// OutputOwners: owner, +// }, +// }}) +// if err != nil { +// log.Fatalf("failed to issue export transaction: %s\n", err) +// } +// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) - importStartTime := time.Now() - importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) - if err != nil { - log.Fatalf("failed to issue import transaction: %s\n", err) - } - log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) -} +// importStartTime := time.Now() +// importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) +// if err != nil { +// log.Fatalf("failed to issue import transaction: %s\n", err) +// } +// log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) +// } diff --git a/wallet/subnet/primary/examples/create-asset/main.go b/wallet/subnet/primary/examples/create-asset/main.go index 30804f083df6..0bccfbb5fc52 100644 --- a/wallet/subnet/primary/examples/create-asset/main.go +++ b/wallet/subnet/primary/examples/create-asset/main.go @@ -30,7 +30,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-chain/main.go b/wallet/subnet/primary/examples/create-chain/main.go index 5e6898a1b649..521a3cca53cf 100644 --- a/wallet/subnet/primary/examples/create-chain/main.go +++ b/wallet/subnet/primary/examples/create-chain/main.go @@ -41,9 +41,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/create-locked-stakeable/main.go b/wallet/subnet/primary/examples/create-locked-stakeable/main.go index e688968e9e8a..92f1b5cb0e1b 100644 --- a/wallet/subnet/primary/examples/create-locked-stakeable/main.go +++ b/wallet/subnet/primary/examples/create-locked-stakeable/main.go @@ -39,7 +39,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-subnet/main.go b/wallet/subnet/primary/examples/create-subnet/main.go index add98ea7931c..3e8d69bc016a 100644 --- a/wallet/subnet/primary/examples/create-subnet/main.go +++ b/wallet/subnet/primary/examples/create-subnet/main.go @@ -28,7 +28,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/remove-subnet-validator/main.go b/wallet/subnet/primary/examples/remove-subnet-validator/main.go index 2842c7c0a790..46f4b85124db 100644 --- a/wallet/subnet/primary/examples/remove-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/remove-subnet-validator/main.go @@ -38,9 +38,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/wallet.go b/wallet/subnet/primary/wallet.go index 54de390d029c..de50d12f866b 100644 --- a/wallet/subnet/primary/wallet.go +++ b/wallet/subnet/primary/wallet.go @@ -11,7 +11,6 @@ import ( "github.com/ava-labs/avalanchego/utils/crypto/keychain" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" @@ -23,13 +22,13 @@ var _ Wallet = (*wallet)(nil) type Wallet interface { P() p.Wallet X() x.Wallet - C() c.Wallet + // C() c.Wallet } type wallet struct { p p.Wallet x x.Wallet - c c.Wallet + // c c.Wallet } func (w *wallet) P() p.Wallet { @@ -40,16 +39,16 @@ func (w *wallet) X() x.Wallet { return w.x } -func (w *wallet) C() c.Wallet { - return w.c -} +// func (w *wallet) C() c.Wallet { +// return w.c +// } // Creates a new default wallet -func NewWallet(p p.Wallet, x x.Wallet, c c.Wallet) Wallet { +func NewWallet(p p.Wallet, x x.Wallet /*, c c.Wallet*/) Wallet { return &wallet{ p: p, x: x, - c: c, + // c: c, } } @@ -58,7 +57,7 @@ func NewWalletWithOptions(w Wallet, options ...common.Option) Wallet { return NewWallet( p.NewWalletWithOptions(w.P(), options...), x.NewWalletWithOptions(w.X(), options...), - c.NewWalletWithOptions(w.C(), options...), + // c.NewWalletWithOptions(w.C(), options...), ) } @@ -67,7 +66,7 @@ type WalletConfig struct { URI string // required // Keys to use for signing all transactions. AVAXKeychain keychain.Keychain // required - EthKeychain c.EthKeychain // required + // EthKeychain c.EthKeychain // required // Set of P-chain transactions that the wallet should know about to be able // to generate transactions. PChainTxs map[ids.ID]*txs.Tx // optional @@ -93,11 +92,11 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { return nil, err } - ethAddrs := config.EthKeychain.EthAddresses() - ethState, err := FetchEthState(ctx, config.URI, ethAddrs) - if err != nil { - return nil, err - } + // ethAddrs := config.EthKeychain.EthAddresses() + // ethState, err := FetchEthState(ctx, config.URI, ethAddrs) + // if err != nil { + // return nil, err + // } pChainTxs := config.PChainTxs if pChainTxs == nil { @@ -127,15 +126,15 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { xBuilder := x.NewBuilder(avaxAddrs, xBackend) xSigner := x.NewSigner(config.AVAXKeychain, xBackend) - cChainID := avaxState.CCTX.BlockchainID() - cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) - cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) - cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) - cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) + // cChainID := avaxState.CCTX.BlockchainID() + // cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) + // cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) + // cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) + // cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) return NewWallet( p.NewWallet(pBuilder, pSigner, avaxState.PClient, pBackend), x.NewWallet(xBuilder, xSigner, avaxState.XClient, xBackend), - c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), + // c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), ), nil } From cde6ae394d0419070cc0906126787dbe823d9dde Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 30 Oct 2023 23:19:42 +0100 Subject: [PATCH 21/36] bumped coreth version --- go.mod | 25 + go.sum | 76 ++ node/node.go | 4 +- tests/e2e/c/dynamic_fees.go | 326 +++---- tests/e2e/c/interchain_workflow.go | 320 +++---- tests/e2e/e2e.go | 116 +-- tests/e2e/p/interchain_workflow.go | 444 +++++----- tests/e2e/x/interchain_workflow.go | 296 +++---- tests/fixture/testnet/config.go | 54 +- vms/example/xsvm/cmd/chain/create/cmd.go | 6 +- wallet/chain/c/backend.go | 300 +++---- wallet/chain/c/builder.go | 792 +++++++++--------- wallet/chain/c/builder_with_options.go | 136 +-- wallet/chain/c/context.go | 130 +-- wallet/chain/c/signer.go | 436 +++++----- wallet/chain/c/wallet.go | 402 ++++----- wallet/chain/c/wallet_with_options.go | 134 +-- wallet/subnet/primary/api.go | 119 +-- wallet/subnet/primary/example_test.go | 2 +- .../add-permissioned-subnet-validator/main.go | 6 +- .../examples/add-primary-validator/main.go | 2 +- .../primary/examples/c-chain-export/main.go | 118 +-- .../primary/examples/c-chain-import/main.go | 126 +-- .../primary/examples/create-asset/main.go | 2 +- .../primary/examples/create-chain/main.go | 6 +- .../examples/create-locked-stakeable/main.go | 2 +- .../primary/examples/create-subnet/main.go | 2 +- .../examples/remove-subnet-validator/main.go | 6 +- wallet/subnet/primary/wallet.go | 41 +- 29 files changed, 2275 insertions(+), 2154 deletions(-) diff --git a/go.mod b/go.mod index 40d59d0cb294..3da9d583a5ae 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/DataDog/zstd v1.5.2 github.com/Microsoft/go-winio v0.5.2 github.com/NYTimes/gziphandler v1.1.1 + github.com/ava-labs/coreth v0.12.8-0.20231030220806-c0a1f8d34b62 github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 github.com/btcsuite/btcd/btcutil v1.1.3 github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 @@ -71,6 +72,7 @@ require ( require ( github.com/BurntSushi/toml v1.2.1 // indirect + github.com/VictoriaMetrics/fastcache v1.10.0 // indirect github.com/benbjohnson/clock v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect @@ -79,26 +81,44 @@ require ( github.com/cockroachdb/errors v1.9.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/redact v1.1.3 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set/v2 v2.1.0 // indirect + github.com/dlclark/regexp2 v1.7.0 // indirect + github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect + github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/frankban/quicktest v1.14.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect + github.com/go-stack/stack v1.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/go-cmp v0.5.9 // indirect + github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 // indirect + github.com/hashicorp/go-bexpr v0.1.10 // indirect + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/klauspost/compress v1.15.15 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/magiconair/properties v1.8.6 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mitchellh/pointerstructure v1.2.0 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect @@ -106,12 +126,17 @@ require ( github.com/prometheus/common v0.39.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sanity-io/litter v1.5.1 // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/status-im/keycard-go v0.2.0 // indirect github.com/subosito/gotenv v1.3.0 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/zondax/hid v0.9.1 // indirect github.com/zondax/ledger-go v0.14.1 // indirect diff --git a/go.sum b/go.sum index 09e5526b3f20..36e8114e65d9 100644 --- a/go.sum +++ b/go.sum @@ -52,12 +52,18 @@ github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cq github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= +github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY= +github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/ava-labs/coreth v0.12.8-0.20231030220806-c0a1f8d34b62 h1:SwAADPPOj2aOZX3rqkKDW/P5g9aKxbVG9tWuy4Md20E= +github.com/ava-labs/coreth v0.12.8-0.20231030220806-c0a1f8d34b62/go.mod h1:ifFsmfVHQrMi4jXcnFXch5N1J2tb/nIx8W5sek7dg7U= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 h1:EdxD90j5sClfL5Ngpz2TlnbnkNYdFPDXa0jDOjam65c= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7/go.mod h1:XhiXSrh90sHUbkERzaxEftCmUz53eCijshDLZ4fByVM= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= @@ -94,13 +100,18 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -130,12 +141,16 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= +github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= @@ -146,6 +161,14 @@ github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6ps github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= +github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= +github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= +github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -162,6 +185,8 @@ github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2 github.com/ethereum/go-ethereum v1.12.0/go.mod h1:/oo2X/dZLJjf2mJ6YT9wcWxa4nNJDBKDBU6sFIpx1Gs= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -170,6 +195,8 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= @@ -193,7 +220,11 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= @@ -278,10 +309,14 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -302,11 +337,17 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 h1:kr3j8iIMR4ywO/O0rvksXaJvauGGCMg2zAZIiNZ9uIQ= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0/go.mod h1:ummNFgdgLhhX7aIiy35vVmQNS0rWXknfPE0qe6fmFXg= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw= +github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e/go.mod h1:j9cQbcqHQujT0oKJ38PylVfqohClLr3CvDC+Qcg+lhU= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8= @@ -318,6 +359,7 @@ github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3 github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -359,6 +401,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -366,6 +409,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= @@ -376,11 +420,17 @@ github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -389,8 +439,11 @@ github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -409,6 +462,8 @@ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -476,6 +531,8 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sanity-io/litter v1.5.1 h1:dwnrSypP6q56o3lFxTU+t2fwQ9A+U5qrXVO4Qg9KwVU= github.com/sanity-io/litter v1.5.1/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0= @@ -511,6 +568,8 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= +github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -540,10 +599,14 @@ github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITn github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= +github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -555,6 +618,8 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1: github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= @@ -564,6 +629,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= @@ -661,6 +727,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -706,6 +773,7 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -729,6 +797,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -793,8 +862,12 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -811,6 +884,7 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -874,6 +948,7 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -998,6 +1073,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= diff --git a/node/node.go b/node/node.go index 3b3974db0401..34293e85b0b6 100644 --- a/node/node.go +++ b/node/node.go @@ -25,7 +25,7 @@ import ( "go.uber.org/zap" - // coreth "github.com/ava-labs/coreth/plugin/evm" + coreth "github.com/ava-labs/coreth/plugin/evm" "github.com/ava-labs/avalanchego/api/admin" "github.com/ava-labs/avalanchego/api/auth" @@ -934,7 +934,7 @@ func (n *Node) initVMs() error { CreateAssetTxFee: n.Config.CreateAssetTxFee, }, }), - // vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), + vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), n.VMManager.RegisterFactory(context.TODO(), secp256k1fx.ID, &secp256k1fx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), nftfx.ID, &nftfx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), propertyfx.ID, &propertyfx.Factory{}), diff --git a/tests/e2e/c/dynamic_fees.go b/tests/e2e/c/dynamic_fees.go index 779c8670be37..edfbef2671a8 100644 --- a/tests/e2e/c/dynamic_fees.go +++ b/tests/e2e/c/dynamic_fees.go @@ -3,166 +3,166 @@ package c -// import ( -// "math/big" -// "strings" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/stretchr/testify/require" - -// "github.com/ethereum/go-ethereum/accounts/abi" -// "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/coreth/core/types" -// "github.com/ava-labs/coreth/params" -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/tests" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/tests/fixture/testnet" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// ) - -// // This test uses the compiled bin for `hashing.sol` as -// // well as its ABI contained in `hashing_contract.go`. - -// var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { -// require := require.New(ginkgo.GinkgoT()) - -// // Need a gas limit much larger than the standard 21_000 to enable -// // the contract to induce a gas price increase -// const largeGasLimit = uint64(8_000_000) - -// // TODO(marun) What is the significance of this value? -// gasTip := big.NewInt(1000 * params.GWei) - -// ginkgo.It("should ensure that the gas price is affected by load", func() { -// ginkgo.By("creating a new private network to ensure isolation from other tests") -// privateNetwork := e2e.Env.NewPrivateNetwork() - -// ginkgo.By("allocating a pre-funded key") -// key := privateNetwork.GetConfig().FundedKeys[0] -// ethAddress := evm.GetEthAddress(key) - -// ginkgo.By("initializing a coreth client") -// node := privateNetwork.GetNodes()[0] -// nodeURI := testnet.NodeURI{ -// NodeID: node.GetID(), -// URI: node.GetProcessContext().URI, -// } -// ethClient := e2e.Env.NewEthClient(nodeURI) - -// ginkgo.By("initializing a transaction signer") -// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) -// require.NoError(err) -// signer := types.NewEIP155Signer(cChainID) -// ecdsaKey := key.ToECDSA() -// sign := func(tx *types.Transaction) *types.Transaction { -// signedTx, err := types.SignTx(tx, signer, ecdsaKey) -// require.NoError(err) -// return signedTx -// } - -// var contractAddress common.Address -// ginkgo.By("deploying an expensive contract", func() { -// // Create transaction -// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) -// require.NoError(err) -// compiledContract := common.Hex2Bytes(hashingCompiledContract) -// tx := types.NewTx(&types.LegacyTx{ -// Nonce: nonce, -// GasPrice: gasTip, -// Gas: largeGasLimit, -// Value: common.Big0, -// Data: compiledContract, -// }) - -// // Send the transaction and wait for acceptance -// signedTx := sign(tx) -// receipt := e2e.SendEthTransaction(ethClient, signedTx) - -// contractAddress = receipt.ContractAddress -// }) - -// var gasPrice *big.Int -// ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { -// // Evaluate the bytes representation of the contract -// hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) -// require.NoError(err) -// contractData, err := hashingABI.Pack("hashIt") -// require.NoError(err) - -// var initialGasPrice *big.Int -// e2e.Eventually(func() bool { -// // Check the gas price -// var err error -// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) -// require.NoError(err) -// if initialGasPrice == nil { -// initialGasPrice = gasPrice -// tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) -// } else if gasPrice.Cmp(initialGasPrice) > 0 { -// // Gas price has increased -// tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) -// return true -// } - -// // Create the transaction -// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) -// require.NoError(err) -// tx := types.NewTx(&types.LegacyTx{ -// Nonce: nonce, -// GasPrice: gasTip, -// Gas: largeGasLimit, -// To: &contractAddress, -// Value: common.Big0, -// Data: contractData, -// }) - -// // Send the transaction and wait for acceptance -// signedTx := sign(tx) -// _ = e2e.SendEthTransaction(ethClient, signedTx) - -// // The gas price will be checked at the start of the next iteration -// return false -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") -// }) - -// ginkgo.By("waiting for the gas price to decrease...", func() { -// initialGasPrice := gasPrice -// e2e.Eventually(func() bool { -// var err error -// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) -// require.NoError(err) -// tests.Outf("{{blue}}.{{/}}") -// return initialGasPrice.Cmp(gasPrice) > 0 -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") -// tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) -// }) - -// ginkgo.By("sending funds at the current gas price", func() { -// // Create a recipient address -// recipientKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) -// recipientEthAddress := evm.GetEthAddress(recipientKey) - -// // Create transaction -// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) -// require.NoError(err) -// tx := types.NewTx(&types.LegacyTx{ -// Nonce: nonce, -// GasPrice: gasPrice, -// Gas: e2e.DefaultGasLimit, -// To: &recipientEthAddress, -// Value: common.Big0, -// }) - -// // Send the transaction and wait for acceptance -// signedTx := sign(tx) -// _ = e2e.SendEthTransaction(ethClient, signedTx) -// }) - -// e2e.CheckBootstrapIsPossible(privateNetwork) -// }) -// }) +import ( + "math/big" + "strings" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/coreth/params" + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/tests" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/tests/fixture/testnet" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +) + +// This test uses the compiled bin for `hashing.sol` as +// well as its ABI contained in `hashing_contract.go`. + +var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { + require := require.New(ginkgo.GinkgoT()) + + // Need a gas limit much larger than the standard 21_000 to enable + // the contract to induce a gas price increase + const largeGasLimit = uint64(8_000_000) + + // TODO(marun) What is the significance of this value? + gasTip := big.NewInt(1000 * params.GWei) + + ginkgo.It("should ensure that the gas price is affected by load", func() { + ginkgo.By("creating a new private network to ensure isolation from other tests") + privateNetwork := e2e.Env.NewPrivateNetwork() + + ginkgo.By("allocating a pre-funded key") + key := privateNetwork.GetConfig().FundedKeys[0] + ethAddress := evm.GetEthAddress(key) + + ginkgo.By("initializing a coreth client") + node := privateNetwork.GetNodes()[0] + nodeURI := testnet.NodeURI{ + NodeID: node.GetID(), + URI: node.GetProcessContext().URI, + } + ethClient := e2e.Env.NewEthClient(nodeURI) + + ginkgo.By("initializing a transaction signer") + cChainID, err := ethClient.ChainID(e2e.DefaultContext()) + require.NoError(err) + signer := types.NewEIP155Signer(cChainID) + ecdsaKey := key.ToECDSA() + sign := func(tx *types.Transaction) *types.Transaction { + signedTx, err := types.SignTx(tx, signer, ecdsaKey) + require.NoError(err) + return signedTx + } + + var contractAddress common.Address + ginkgo.By("deploying an expensive contract", func() { + // Create transaction + nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) + require.NoError(err) + compiledContract := common.Hex2Bytes(hashingCompiledContract) + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + GasPrice: gasTip, + Gas: largeGasLimit, + Value: common.Big0, + Data: compiledContract, + }) + + // Send the transaction and wait for acceptance + signedTx := sign(tx) + receipt := e2e.SendEthTransaction(ethClient, signedTx) + + contractAddress = receipt.ContractAddress + }) + + var gasPrice *big.Int + ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { + // Evaluate the bytes representation of the contract + hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) + require.NoError(err) + contractData, err := hashingABI.Pack("hashIt") + require.NoError(err) + + var initialGasPrice *big.Int + e2e.Eventually(func() bool { + // Check the gas price + var err error + gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) + require.NoError(err) + if initialGasPrice == nil { + initialGasPrice = gasPrice + tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) + } else if gasPrice.Cmp(initialGasPrice) > 0 { + // Gas price has increased + tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) + return true + } + + // Create the transaction + nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) + require.NoError(err) + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + GasPrice: gasTip, + Gas: largeGasLimit, + To: &contractAddress, + Value: common.Big0, + Data: contractData, + }) + + // Send the transaction and wait for acceptance + signedTx := sign(tx) + _ = e2e.SendEthTransaction(ethClient, signedTx) + + // The gas price will be checked at the start of the next iteration + return false + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") + }) + + ginkgo.By("waiting for the gas price to decrease...", func() { + initialGasPrice := gasPrice + e2e.Eventually(func() bool { + var err error + gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) + require.NoError(err) + tests.Outf("{{blue}}.{{/}}") + return initialGasPrice.Cmp(gasPrice) > 0 + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") + tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) + }) + + ginkgo.By("sending funds at the current gas price", func() { + // Create a recipient address + recipientKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + recipientEthAddress := evm.GetEthAddress(recipientKey) + + // Create transaction + nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) + require.NoError(err) + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + GasPrice: gasPrice, + Gas: e2e.DefaultGasLimit, + To: &recipientEthAddress, + Value: common.Big0, + }) + + // Send the transaction and wait for acceptance + signedTx := sign(tx) + _ = e2e.SendEthTransaction(ethClient, signedTx) + }) + + e2e.CheckBootstrapIsPossible(privateNetwork) + }) +}) diff --git a/tests/e2e/c/interchain_workflow.go b/tests/e2e/c/interchain_workflow.go index d13c4b8db1ce..8bed85eb1bd9 100644 --- a/tests/e2e/c/interchain_workflow.go +++ b/tests/e2e/c/interchain_workflow.go @@ -3,163 +3,163 @@ package c -// import ( -// "math/big" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/stretchr/testify/require" - -// "github.com/ava-labs/coreth/core/types" -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { -// require := require.New(ginkgo.GinkgoT()) - -// const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer - -// ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { -// ginkgo.By("initializing a new eth client") -// // Select a random node URI to use for both the eth client and -// // the wallet to avoid having to verify that all nodes are at -// // the same height before initializing the wallet. -// nodeURI := e2e.Env.GetRandomNodeURI() -// ethClient := e2e.Env.NewEthClient(nodeURI) - -// ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") -// senderKey := e2e.Env.AllocateFundedKey() -// senderEthAddress := evm.GetEthAddress(senderKey) -// recipientKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) -// recipientEthAddress := evm.GetEthAddress(recipientKey) - -// ginkgo.By("sending funds from one address to another on the C-Chain", func() { -// // Create transaction -// acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) -// require.NoError(err) -// gasPrice := e2e.SuggestGasPrice(ethClient) -// tx := types.NewTransaction( -// acceptedNonce, -// recipientEthAddress, -// big.NewInt(int64(txAmount)), -// e2e.DefaultGasLimit, -// gasPrice, -// nil, -// ) - -// // Sign transaction -// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) -// require.NoError(err) -// signer := types.NewEIP155Signer(cChainID) -// signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) -// require.NoError(err) - -// _ = e2e.SendEthTransaction(ethClient, signedTx) - -// ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") -// e2e.Eventually(func() bool { -// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) -// require.NoError(err) -// return balance.Cmp(big.NewInt(0)) > 0 -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") -// }) - -// // Wallet must be initialized after sending funds on the -// // C-Chain with the same node URI to ensure wallet state -// // matches on-chain state. -// ginkgo.By("initializing a keychain and associated wallet") -// keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) -// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) -// xWallet := baseWallet.X() -// cWallet := baseWallet.C() -// pWallet := baseWallet.P() - -// ginkgo.By("defining common configuration") -// avaxAssetID := xWallet.AVAXAssetID() -// // Use the same owner for import funds to X-Chain and P-Chain -// recipientOwner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// recipientKey.Address(), -// }, -// } -// // Use the same outputs for both X-Chain and P-Chain exports -// exportOutputs := []*secp256k1fx.TransferOutput{ -// { -// Amt: txAmount, -// OutputOwners: secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// keychain.Keys[0].Address(), -// }, -// }, -// }, -// } - -// ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { -// _, err := cWallet.IssueExportTx( -// xWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { -// _, err := xWallet.IssueImportTx( -// cWallet.BlockchainID(), -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { -// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { -// _, err := cWallet.IssueExportTx( -// constants.PlatformChainID, -// exportOutputs, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { -// _, err = pWallet.IssueImportTx( -// cWallet.BlockchainID(), -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { -// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) -// }) -// }) +import ( + "math/big" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { + require := require.New(ginkgo.GinkgoT()) + + const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer + + ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { + ginkgo.By("initializing a new eth client") + // Select a random node URI to use for both the eth client and + // the wallet to avoid having to verify that all nodes are at + // the same height before initializing the wallet. + nodeURI := e2e.Env.GetRandomNodeURI() + ethClient := e2e.Env.NewEthClient(nodeURI) + + ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") + senderKey := e2e.Env.AllocateFundedKey() + senderEthAddress := evm.GetEthAddress(senderKey) + recipientKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + recipientEthAddress := evm.GetEthAddress(recipientKey) + + ginkgo.By("sending funds from one address to another on the C-Chain", func() { + // Create transaction + acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) + require.NoError(err) + gasPrice := e2e.SuggestGasPrice(ethClient) + tx := types.NewTransaction( + acceptedNonce, + recipientEthAddress, + big.NewInt(int64(txAmount)), + e2e.DefaultGasLimit, + gasPrice, + nil, + ) + + // Sign transaction + cChainID, err := ethClient.ChainID(e2e.DefaultContext()) + require.NoError(err) + signer := types.NewEIP155Signer(cChainID) + signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) + require.NoError(err) + + _ = e2e.SendEthTransaction(ethClient, signedTx) + + ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") + e2e.Eventually(func() bool { + balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) + require.NoError(err) + return balance.Cmp(big.NewInt(0)) > 0 + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") + }) + + // Wallet must be initialized after sending funds on the + // C-Chain with the same node URI to ensure wallet state + // matches on-chain state. + ginkgo.By("initializing a keychain and associated wallet") + keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) + baseWallet := e2e.Env.NewWallet(keychain, nodeURI) + xWallet := baseWallet.X() + cWallet := baseWallet.C() + pWallet := baseWallet.P() + + ginkgo.By("defining common configuration") + avaxAssetID := xWallet.AVAXAssetID() + // Use the same owner for import funds to X-Chain and P-Chain + recipientOwner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + recipientKey.Address(), + }, + } + // Use the same outputs for both X-Chain and P-Chain exports + exportOutputs := []*secp256k1fx.TransferOutput{ + { + Amt: txAmount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + keychain.Keys[0].Address(), + }, + }, + }, + } + + ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { + _, err := cWallet.IssueExportTx( + xWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { + _, err := xWallet.IssueImportTx( + cWallet.BlockchainID(), + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { + balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { + _, err := cWallet.IssueExportTx( + constants.PlatformChainID, + exportOutputs, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { + _, err = pWallet.IssueImportTx( + cWallet.BlockchainID(), + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { + balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) + }) +}) diff --git a/tests/e2e/e2e.go b/tests/e2e/e2e.go index 8b70b9f9ca3f..130f33f1197c 100644 --- a/tests/e2e/e2e.go +++ b/tests/e2e/e2e.go @@ -7,15 +7,23 @@ package e2e import ( "context" "encoding/json" + "errors" + "fmt" + "math/big" "math/rand" "os" "path/filepath" + "strings" "time" ginkgo "github.com/onsi/ginkgo/v2" "github.com/stretchr/testify/require" + "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/coreth/ethclient" + "github.com/ava-labs/coreth/interfaces" + "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/tests" "github.com/ava-labs/avalanchego/tests/fixture" @@ -126,7 +134,7 @@ func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain, nodeURI tes baseWallet, err := primary.MakeWallet(DefaultContext(), &primary.WalletConfig{ URI: nodeURI.URI, AVAXKeychain: keychain, - // EthKeychain: keychain, + EthKeychain: keychain, }) te.require.NoError(err) return primary.NewWalletWithOptions( @@ -139,16 +147,16 @@ func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain, nodeURI tes ) } -// // Create a new eth client targeting the specified node URI. -// // TODO(marun) Make this a regular function. -// func (te *TestEnvironment) NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { -// tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) -// nodeAddress := strings.Split(nodeURI.URI, "//")[1] -// uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) -// client, err := ethclient.Dial(uri) -// te.require.NoError(err) -// return client -// } +// Create a new eth client targeting the specified node URI. +// TODO(marun) Make this a regular function. +func (te *TestEnvironment) NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { + tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) + nodeAddress := strings.Split(nodeURI.URI, "//")[1] + uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) + client, err := ethclient.Dial(uri) + te.require.NoError(err) + return client +} // Create a new private network that is not shared with other tests. func (te *TestEnvironment) NewPrivateNetwork() testnet.Network { @@ -223,49 +231,49 @@ func WaitForHealthy(node testnet.Node) { require.NoError(ginkgo.GinkgoT(), testnet.WaitForHealthy(DefaultContext(), node)) } -// // Sends an eth transaction, waits for the transaction receipt to be issued -// // and checks that the receipt indicates success. -// func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { -// require := require.New(ginkgo.GinkgoT()) - -// txID := signedTx.Hash() -// tests.Outf(" sending eth transaction with ID: %s\n", txID) - -// require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) - -// // Wait for the receipt -// var receipt *types.Receipt -// Eventually(func() bool { -// var err error -// receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) -// if errors.Is(err, interfaces.NotFound) { -// return false // Transaction is still pending -// } -// require.NoError(err) -// return true -// }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") - -// require.Equal(receipt.Status, types.ReceiptStatusSuccessful) -// return receipt -// } - -// // Determines the suggested gas price for the configured client that will -// // maximize the chances of transaction acceptance. -// func SuggestGasPrice(ethClient ethclient.Client) *big.Int { -// gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) -// require.NoError(ginkgo.GinkgoT(), err) -// // Double the suggested gas price to maximize the chances of -// // acceptance. Maybe this can be revisited pending resolution of -// // https://github.com/ava-labs/coreth/issues/314. -// gasPrice.Add(gasPrice, gasPrice) -// return gasPrice -// } - -// // Helper simplifying use via an option of a gas price appropriate for testing. -// func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { -// baseFee := SuggestGasPrice(ethClient) -// return common.WithBaseFee(baseFee) -// } +// Sends an eth transaction, waits for the transaction receipt to be issued +// and checks that the receipt indicates success. +func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { + require := require.New(ginkgo.GinkgoT()) + + txID := signedTx.Hash() + tests.Outf(" sending eth transaction with ID: %s\n", txID) + + require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) + + // Wait for the receipt + var receipt *types.Receipt + Eventually(func() bool { + var err error + receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) + if errors.Is(err, interfaces.NotFound) { + return false // Transaction is still pending + } + require.NoError(err) + return true + }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") + + require.Equal(receipt.Status, types.ReceiptStatusSuccessful) + return receipt +} + +// Determines the suggested gas price for the configured client that will +// maximize the chances of transaction acceptance. +func SuggestGasPrice(ethClient ethclient.Client) *big.Int { + gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) + require.NoError(ginkgo.GinkgoT(), err) + // Double the suggested gas price to maximize the chances of + // acceptance. Maybe this can be revisited pending resolution of + // https://github.com/ava-labs/coreth/issues/314. + gasPrice.Add(gasPrice, gasPrice) + return gasPrice +} + +// Helper simplifying use via an option of a gas price appropriate for testing. +func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { + baseFee := SuggestGasPrice(ethClient) + return common.WithBaseFee(baseFee) +} // Verify that a new node can bootstrap into the network. func CheckBootstrapIsPossible(network testnet.Network) { diff --git a/tests/e2e/p/interchain_workflow.go b/tests/e2e/p/interchain_workflow.go index d3715c254e90..729418adbd97 100644 --- a/tests/e2e/p/interchain_workflow.go +++ b/tests/e2e/p/interchain_workflow.go @@ -3,225 +3,225 @@ package p -// import ( -// "math/big" -// "time" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/spf13/cast" - -// "github.com/stretchr/testify/require" - -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/api/info" -// "github.com/ava-labs/avalanchego/config" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/tests/fixture/testnet" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/platformvm/reward" -// "github.com/ava-labs/avalanchego/vms/platformvm/txs" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { -// require := require.New(ginkgo.GinkgoT()) - -// const ( -// transferAmount = 10 * units.Avax -// weight = 2_000 * units.Avax // Used for both validation and delegation -// ) - -// ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { -// network := e2e.Env.GetNetwork() - -// ginkgo.By("checking that the network has a compatible minimum stake duration", func() { -// minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) -// require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) -// }) - -// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") -// recipientKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) -// keychain := e2e.Env.NewKeychain(1) -// keychain.Add(recipientKey) -// nodeURI := e2e.Env.GetRandomNodeURI() -// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) -// xWallet := baseWallet.X() -// cWallet := baseWallet.C() -// pWallet := baseWallet.P() - -// ginkgo.By("defining common configuration") -// recipientEthAddress := evm.GetEthAddress(recipientKey) -// avaxAssetID := xWallet.AVAXAssetID() -// // Use the same owner for sending to X-Chain and importing funds to P-Chain -// recipientOwner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// recipientKey.Address(), -// }, -// } -// // Use the same outputs for both X-Chain and C-Chain exports -// exportOutputs := []*avax.TransferableOutput{ -// { -// Asset: avax.Asset{ -// ID: avaxAssetID, -// }, -// Out: &secp256k1fx.TransferOutput{ -// Amt: transferAmount, -// OutputOwners: secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// keychain.Keys[0].Address(), -// }, -// }, -// }, -// }, -// } - -// ginkgo.By("adding new node and waiting for it to report healthy") -// node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) -// e2e.WaitForHealthy(node) - -// ginkgo.By("retrieving new node's id and pop") -// infoClient := info.NewClient(node.GetProcessContext().URI) -// nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) -// require.NoError(err) - -// ginkgo.By("adding the new node as a validator", func() { -// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) -// // Validation duration doesn't actually matter to this -// // test - it is only ensuring that adding a validator -// // doesn't break interchain transfer. -// endTime := startTime.Add(30 * time.Second) - -// rewardKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) - -// const ( -// delegationPercent = 0.10 // 10% -// delegationShare = reward.PercentDenominator * delegationPercent -// ) - -// _, err = pWallet.IssueAddPermissionlessValidatorTx( -// &txs.SubnetValidator{ -// Validator: txs.Validator{ -// NodeID: nodeID, -// Start: uint64(startTime.Unix()), -// End: uint64(endTime.Unix()), -// Wght: weight, -// }, -// Subnet: constants.PrimaryNetworkID, -// }, -// nodePOP, -// pWallet.AVAXAssetID(), -// &secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{rewardKey.Address()}, -// }, -// &secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{rewardKey.Address()}, -// }, -// delegationShare, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("adding a delegator to the new node", func() { -// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) -// // Delegation duration doesn't actually matter to this -// // test - it is only ensuring that adding a delegator -// // doesn't break interchain transfer. -// endTime := startTime.Add(15 * time.Second) - -// rewardKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) - -// _, err = pWallet.IssueAddPermissionlessDelegatorTx( -// &txs.SubnetValidator{ -// Validator: txs.Validator{ -// NodeID: nodeID, -// Start: uint64(startTime.Unix()), -// End: uint64(endTime.Unix()), -// Wght: weight, -// }, -// Subnet: constants.PrimaryNetworkID, -// }, -// pWallet.AVAXAssetID(), -// &secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{rewardKey.Address()}, -// }, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { -// _, err := pWallet.IssueExportTx( -// xWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { -// _, err := xWallet.IssueImportTx( -// constants.PlatformChainID, -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { -// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { -// _, err := pWallet.IssueExportTx( -// cWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("initializing a new eth client") -// ethClient := e2e.Env.NewEthClient(nodeURI) - -// ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { -// _, err := cWallet.IssueImportTx( -// constants.PlatformChainID, -// recipientEthAddress, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") -// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) -// require.NoError(err) -// require.Positive(balance.Cmp(big.NewInt(0))) - -// ginkgo.By("stopping validator node to free up resources for a bootstrap check") -// require.NoError(node.Stop()) - -// e2e.CheckBootstrapIsPossible(network) -// }) -// }) +import ( + "math/big" + "time" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/spf13/cast" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/api/info" + "github.com/ava-labs/avalanchego/config" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/tests/fixture/testnet" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/platformvm/reward" + "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { + require := require.New(ginkgo.GinkgoT()) + + const ( + transferAmount = 10 * units.Avax + weight = 2_000 * units.Avax // Used for both validation and delegation + ) + + ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { + network := e2e.Env.GetNetwork() + + ginkgo.By("checking that the network has a compatible minimum stake duration", func() { + minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) + require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) + }) + + ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") + recipientKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + keychain := e2e.Env.NewKeychain(1) + keychain.Add(recipientKey) + nodeURI := e2e.Env.GetRandomNodeURI() + baseWallet := e2e.Env.NewWallet(keychain, nodeURI) + xWallet := baseWallet.X() + cWallet := baseWallet.C() + pWallet := baseWallet.P() + + ginkgo.By("defining common configuration") + recipientEthAddress := evm.GetEthAddress(recipientKey) + avaxAssetID := xWallet.AVAXAssetID() + // Use the same owner for sending to X-Chain and importing funds to P-Chain + recipientOwner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + recipientKey.Address(), + }, + } + // Use the same outputs for both X-Chain and C-Chain exports + exportOutputs := []*avax.TransferableOutput{ + { + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: transferAmount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + keychain.Keys[0].Address(), + }, + }, + }, + }, + } + + ginkgo.By("adding new node and waiting for it to report healthy") + node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) + e2e.WaitForHealthy(node) + + ginkgo.By("retrieving new node's id and pop") + infoClient := info.NewClient(node.GetProcessContext().URI) + nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) + require.NoError(err) + + ginkgo.By("adding the new node as a validator", func() { + startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) + // Validation duration doesn't actually matter to this + // test - it is only ensuring that adding a validator + // doesn't break interchain transfer. + endTime := startTime.Add(30 * time.Second) + + rewardKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + + const ( + delegationPercent = 0.10 // 10% + delegationShare = reward.PercentDenominator * delegationPercent + ) + + _, err = pWallet.IssueAddPermissionlessValidatorTx( + &txs.SubnetValidator{ + Validator: txs.Validator{ + NodeID: nodeID, + Start: uint64(startTime.Unix()), + End: uint64(endTime.Unix()), + Wght: weight, + }, + Subnet: constants.PrimaryNetworkID, + }, + nodePOP, + pWallet.AVAXAssetID(), + &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{rewardKey.Address()}, + }, + &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{rewardKey.Address()}, + }, + delegationShare, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("adding a delegator to the new node", func() { + startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) + // Delegation duration doesn't actually matter to this + // test - it is only ensuring that adding a delegator + // doesn't break interchain transfer. + endTime := startTime.Add(15 * time.Second) + + rewardKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + + _, err = pWallet.IssueAddPermissionlessDelegatorTx( + &txs.SubnetValidator{ + Validator: txs.Validator{ + NodeID: nodeID, + Start: uint64(startTime.Unix()), + End: uint64(endTime.Unix()), + Wght: weight, + }, + Subnet: constants.PrimaryNetworkID, + }, + pWallet.AVAXAssetID(), + &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{rewardKey.Address()}, + }, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { + _, err := pWallet.IssueExportTx( + xWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { + _, err := xWallet.IssueImportTx( + constants.PlatformChainID, + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { + balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { + _, err := pWallet.IssueExportTx( + cWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("initializing a new eth client") + ethClient := e2e.Env.NewEthClient(nodeURI) + + ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { + _, err := cWallet.IssueImportTx( + constants.PlatformChainID, + recipientEthAddress, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") + balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) + require.NoError(err) + require.Positive(balance.Cmp(big.NewInt(0))) + + ginkgo.By("stopping validator node to free up resources for a bootstrap check") + require.NoError(node.Stop()) + + e2e.CheckBootstrapIsPossible(network) + }) +}) diff --git a/tests/e2e/x/interchain_workflow.go b/tests/e2e/x/interchain_workflow.go index 3b7a4c988405..6d335199b5b9 100644 --- a/tests/e2e/x/interchain_workflow.go +++ b/tests/e2e/x/interchain_workflow.go @@ -3,151 +3,151 @@ package x -// import ( -// "math/big" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/stretchr/testify/require" - -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { -// require := require.New(ginkgo.GinkgoT()) - -// const transferAmount = 10 * units.Avax - -// ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { -// nodeURI := e2e.Env.GetRandomNodeURI() - -// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") -// recipientKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) -// keychain := e2e.Env.NewKeychain(1) -// keychain.Add(recipientKey) -// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) -// xWallet := baseWallet.X() -// cWallet := baseWallet.C() -// pWallet := baseWallet.P() - -// ginkgo.By("defining common configuration") -// recipientEthAddress := evm.GetEthAddress(recipientKey) -// avaxAssetID := xWallet.AVAXAssetID() -// // Use the same owner for sending to X-Chain and importing funds to P-Chain -// recipientOwner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// recipientKey.Address(), -// }, -// } -// // Use the same outputs for both C-Chain and P-Chain exports -// exportOutputs := []*avax.TransferableOutput{ -// { -// Asset: avax.Asset{ -// ID: avaxAssetID, -// }, -// Out: &secp256k1fx.TransferOutput{ -// Amt: transferAmount, -// OutputOwners: secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// keychain.Keys[0].Address(), -// }, -// }, -// }, -// }, -// } - -// ginkgo.By("sending funds from one address to another on the X-Chain", func() { -// _, err = xWallet.IssueBaseTx( -// []*avax.TransferableOutput{{ -// Asset: avax.Asset{ -// ID: avaxAssetID, -// }, -// Out: &secp256k1fx.TransferOutput{ -// Amt: transferAmount, -// OutputOwners: recipientOwner, -// }, -// }}, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { -// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { -// _, err := xWallet.IssueExportTx( -// cWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("initializing a new eth client") -// ethClient := e2e.Env.NewEthClient(nodeURI) - -// ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { -// _, err := cWallet.IssueImportTx( -// xWallet.BlockchainID(), -// recipientEthAddress, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") -// e2e.Eventually(func() bool { -// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) -// require.NoError(err) -// return balance.Cmp(big.NewInt(0)) > 0 -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") - -// ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { -// _, err := xWallet.IssueExportTx( -// constants.PlatformChainID, -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { -// _, err := pWallet.IssueImportTx( -// xWallet.BlockchainID(), -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { -// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) -// }) -// }) +import ( + "math/big" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { + require := require.New(ginkgo.GinkgoT()) + + const transferAmount = 10 * units.Avax + + ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { + nodeURI := e2e.Env.GetRandomNodeURI() + + ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") + recipientKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + keychain := e2e.Env.NewKeychain(1) + keychain.Add(recipientKey) + baseWallet := e2e.Env.NewWallet(keychain, nodeURI) + xWallet := baseWallet.X() + cWallet := baseWallet.C() + pWallet := baseWallet.P() + + ginkgo.By("defining common configuration") + recipientEthAddress := evm.GetEthAddress(recipientKey) + avaxAssetID := xWallet.AVAXAssetID() + // Use the same owner for sending to X-Chain and importing funds to P-Chain + recipientOwner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + recipientKey.Address(), + }, + } + // Use the same outputs for both C-Chain and P-Chain exports + exportOutputs := []*avax.TransferableOutput{ + { + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: transferAmount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + keychain.Keys[0].Address(), + }, + }, + }, + }, + } + + ginkgo.By("sending funds from one address to another on the X-Chain", func() { + _, err = xWallet.IssueBaseTx( + []*avax.TransferableOutput{{ + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: transferAmount, + OutputOwners: recipientOwner, + }, + }}, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { + balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { + _, err := xWallet.IssueExportTx( + cWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("initializing a new eth client") + ethClient := e2e.Env.NewEthClient(nodeURI) + + ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { + _, err := cWallet.IssueImportTx( + xWallet.BlockchainID(), + recipientEthAddress, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") + e2e.Eventually(func() bool { + balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) + require.NoError(err) + return balance.Cmp(big.NewInt(0)) > 0 + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") + + ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { + _, err := xWallet.IssueExportTx( + constants.PlatformChainID, + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { + _, err := pWallet.IssueImportTx( + xWallet.BlockchainID(), + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { + balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) + }) +}) diff --git a/tests/fixture/testnet/config.go b/tests/fixture/testnet/config.go index 0f24b60b50db..425aa646a690 100644 --- a/tests/fixture/testnet/config.go +++ b/tests/fixture/testnet/config.go @@ -15,6 +15,10 @@ import ( "github.com/spf13/cast" + "github.com/ava-labs/coreth/core" + "github.com/ava-labs/coreth/params" + "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/avalanchego/config" "github.com/ava-labs/avalanchego/genesis" "github.com/ava-labs/avalanchego/ids" @@ -139,15 +143,15 @@ func (c *NetworkConfig) EnsureGenesis(networkID uint32, validatorIDs []ids.NodeI // Ensure pre-funded keys have arbitrary large balances on both chains to support testing xChainBalances := make(XChainBalanceMap, len(c.FundedKeys)) - // cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) - // for _, key := range c.FundedKeys { - // xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount - // cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ - // Balance: DefaultFundedKeyCChainAmount, - // } - // } - - genesis, err := NewTestGenesis(networkID, xChainBalances /*, cChainBalances*/, validatorIDs) + cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) + for _, key := range c.FundedKeys { + xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount + cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ + Balance: DefaultFundedKeyCChainAmount, + } + } + + genesis, err := NewTestGenesis(networkID, xChainBalances, cChainBalances, validatorIDs) if err != nil { return err } @@ -307,7 +311,7 @@ type XChainBalanceMap map[ids.ShortID]uint64 func NewTestGenesis( networkID uint32, xChainBalances XChainBalanceMap, - // cChainBalances core.GenesisAlloc, + cChainBalances core.GenesisAlloc, validatorIDs []ids.NodeID, ) (*genesis.UnparsedConfig, error) { // Validate inputs @@ -318,7 +322,7 @@ func NewTestGenesis( if len(validatorIDs) == 0 { return nil, errMissingValidatorsForGenesis } - if len(xChainBalances) == 0 /*|| len(cChainBalances) == 0*/ { + if len(xChainBalances) == 0 || len(cChainBalances) == 0 { return nil, errMissingBalancesForGenesis } @@ -390,20 +394,20 @@ func NewTestGenesis( ) } - // // Define C-Chain genesis - // cChainGenesis := &core.Genesis{ - // Config: ¶ms.ChainConfig{ - // ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary - // }, - // Difficulty: big.NewInt(0), // Difficulty is a mandatory field - // GasLimit: DefaultGasLimit, - // // Alloc: cChainBalances, - // } - // cChainGenesisBytes, err := json.Marshal(cChainGenesis) - // if err != nil { - // return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) - // } - // config.CChainGenesis = string(cChainGenesisBytes) + // Define C-Chain genesis + cChainGenesis := &core.Genesis{ + Config: ¶ms.ChainConfig{ + ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary + }, + Difficulty: big.NewInt(0), // Difficulty is a mandatory field + GasLimit: DefaultGasLimit, + Alloc: cChainBalances, + } + cChainGenesisBytes, err := json.Marshal(cChainGenesis) + if err != nil { + return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) + } + config.CChainGenesis = string(cChainGenesisBytes) // Give staking rewards for initial validators to a random address. Any testing of staking rewards // will be easier to perform with nodes other than the initial validators since the timing of diff --git a/vms/example/xsvm/cmd/chain/create/cmd.go b/vms/example/xsvm/cmd/chain/create/cmd.go index 043b4298dcdf..1f00491a4ce6 100644 --- a/vms/example/xsvm/cmd/chain/create/cmd.go +++ b/vms/example/xsvm/cmd/chain/create/cmd.go @@ -42,9 +42,9 @@ func createFunc(c *cobra.Command, args []string) error { // that [uri] is hosting. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: config.URI, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: config.URI, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(config.SubnetID), }) if err != nil { diff --git a/wallet/chain/c/backend.go b/wallet/chain/c/backend.go index b88c8c643bc3..0a735116b646 100644 --- a/wallet/chain/c/backend.go +++ b/wallet/chain/c/backend.go @@ -3,153 +3,153 @@ package c -// import ( -// "errors" -// "fmt" -// "math/big" -// "sync" - -// stdcontext "context" - -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/database" -// "github.com/ava-labs/avalanchego/utils/math" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var ( -// _ Backend = (*backend)(nil) - -// errUnknownTxType = errors.New("unknown tx type") -// ) - -// // Backend defines the full interface required to support a C-chain wallet. -// type Backend interface { -// common.ChainUTXOs -// BuilderBackend -// SignerBackend - -// AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error -// } - -// type backend struct { -// Context -// common.ChainUTXOs - -// accountsLock sync.RWMutex -// accounts map[ethcommon.Address]*Account -// } - -// type Account struct { -// Balance *big.Int -// Nonce uint64 -// } - -// func NewBackend( -// ctx Context, -// utxos common.ChainUTXOs, -// accounts map[ethcommon.Address]*Account, -// ) Backend { -// return &backend{ -// Context: ctx, -// ChainUTXOs: utxos, -// accounts: accounts, -// } -// } - -// func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { -// switch tx := tx.UnsignedAtomicTx.(type) { -// case *evm.UnsignedImportTx: -// for _, input := range tx.ImportedInputs { -// utxoID := input.InputID() -// if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { -// return err -// } -// } - -// b.accountsLock.Lock() -// defer b.accountsLock.Unlock() - -// for _, output := range tx.Outs { -// account, ok := b.accounts[output.Address] -// if !ok { -// continue -// } - -// balance := new(big.Int).SetUint64(output.Amount) -// balance.Mul(balance, avaxConversionRate) -// account.Balance.Add(account.Balance, balance) -// } -// case *evm.UnsignedExportTx: -// txID := tx.ID() -// for i, out := range tx.ExportedOutputs { -// err := b.AddUTXO( -// ctx, -// tx.DestinationChain, -// &avax.UTXO{ -// UTXOID: avax.UTXOID{ -// TxID: txID, -// OutputIndex: uint32(i), -// }, -// Asset: avax.Asset{ID: out.AssetID()}, -// Out: out.Out, -// }, -// ) -// if err != nil { -// return err -// } -// } - -// b.accountsLock.Lock() -// defer b.accountsLock.Unlock() - -// for _, input := range tx.Ins { -// account, ok := b.accounts[input.Address] -// if !ok { -// continue -// } - -// balance := new(big.Int).SetUint64(input.Amount) -// balance.Mul(balance, avaxConversionRate) -// if account.Balance.Cmp(balance) == -1 { -// return errInsufficientFunds -// } -// account.Balance.Sub(account.Balance, balance) - -// newNonce, err := math.Add64(input.Nonce, 1) -// if err != nil { -// return err -// } -// account.Nonce = newNonce -// } -// default: -// return fmt.Errorf("%w: %T", errUnknownTxType, tx) -// } -// return nil -// } - -// func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { -// b.accountsLock.RLock() -// defer b.accountsLock.RUnlock() - -// account, exists := b.accounts[addr] -// if !exists { -// return nil, database.ErrNotFound -// } -// return account.Balance, nil -// } - -// func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { -// b.accountsLock.RLock() -// defer b.accountsLock.RUnlock() - -// account, exists := b.accounts[addr] -// if !exists { -// return 0, database.ErrNotFound -// } -// return account.Nonce, nil -// } +import ( + "errors" + "fmt" + "math/big" + "sync" + + stdcontext "context" + + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/utils/math" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var ( + _ Backend = (*backend)(nil) + + errUnknownTxType = errors.New("unknown tx type") +) + +// Backend defines the full interface required to support a C-chain wallet. +type Backend interface { + common.ChainUTXOs + BuilderBackend + SignerBackend + + AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error +} + +type backend struct { + Context + common.ChainUTXOs + + accountsLock sync.RWMutex + accounts map[ethcommon.Address]*Account +} + +type Account struct { + Balance *big.Int + Nonce uint64 +} + +func NewBackend( + ctx Context, + utxos common.ChainUTXOs, + accounts map[ethcommon.Address]*Account, +) Backend { + return &backend{ + Context: ctx, + ChainUTXOs: utxos, + accounts: accounts, + } +} + +func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { + switch tx := tx.UnsignedAtomicTx.(type) { + case *evm.UnsignedImportTx: + for _, input := range tx.ImportedInputs { + utxoID := input.InputID() + if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { + return err + } + } + + b.accountsLock.Lock() + defer b.accountsLock.Unlock() + + for _, output := range tx.Outs { + account, ok := b.accounts[output.Address] + if !ok { + continue + } + + balance := new(big.Int).SetUint64(output.Amount) + balance.Mul(balance, avaxConversionRate) + account.Balance.Add(account.Balance, balance) + } + case *evm.UnsignedExportTx: + txID := tx.ID() + for i, out := range tx.ExportedOutputs { + err := b.AddUTXO( + ctx, + tx.DestinationChain, + &avax.UTXO{ + UTXOID: avax.UTXOID{ + TxID: txID, + OutputIndex: uint32(i), + }, + Asset: avax.Asset{ID: out.AssetID()}, + Out: out.Out, + }, + ) + if err != nil { + return err + } + } + + b.accountsLock.Lock() + defer b.accountsLock.Unlock() + + for _, input := range tx.Ins { + account, ok := b.accounts[input.Address] + if !ok { + continue + } + + balance := new(big.Int).SetUint64(input.Amount) + balance.Mul(balance, avaxConversionRate) + if account.Balance.Cmp(balance) == -1 { + return errInsufficientFunds + } + account.Balance.Sub(account.Balance, balance) + + newNonce, err := math.Add64(input.Nonce, 1) + if err != nil { + return err + } + account.Nonce = newNonce + } + default: + return fmt.Errorf("%w: %T", errUnknownTxType, tx) + } + return nil +} + +func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { + b.accountsLock.RLock() + defer b.accountsLock.RUnlock() + + account, exists := b.accounts[addr] + if !exists { + return nil, database.ErrNotFound + } + return account.Balance, nil +} + +func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { + b.accountsLock.RLock() + defer b.accountsLock.RUnlock() + + account, exists := b.accounts[addr] + if !exists { + return 0, database.ErrNotFound + } + return account.Nonce, nil +} diff --git a/wallet/chain/c/builder.go b/wallet/chain/c/builder.go index c51d2647777e..d2d088e88a53 100644 --- a/wallet/chain/c/builder.go +++ b/wallet/chain/c/builder.go @@ -3,399 +3,399 @@ package c -// import ( -// "errors" -// "math/big" - -// stdcontext "context" - -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils" -// "github.com/ava-labs/avalanchego/utils/math" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// const avaxConversionRateInt = 1_000_000_000 - -// var ( -// _ Builder = (*builder)(nil) - -// errInsufficientFunds = errors.New("insufficient funds") - -// // avaxConversionRate is the conversion rate between the smallest -// // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest -// // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. -// // -// // This is only required for AVAX because the denomination of 1 AVAX is 9 -// // decimal places on the X and P chains, but is 18 decimal places within the -// // EVM. -// avaxConversionRate = big.NewInt(avaxConversionRateInt) -// ) - -// // Builder provides a convenient interface for building unsigned C-chain -// // transactions. -// type Builder interface { -// // GetBalance calculates the amount of AVAX that this builder has control -// // over. -// GetBalance( -// options ...common.Option, -// ) (*big.Int, error) - -// // GetImportableBalance calculates the amount of AVAX that this builder -// // could import from the provided chain. -// // -// // - [chainID] specifies the chain the funds are from. -// GetImportableBalance( -// chainID ids.ID, -// options ...common.Option, -// ) (uint64, error) - -// // NewImportTx creates an import transaction that attempts to consume all -// // the available UTXOs and import the funds to [to]. -// // -// // - [chainID] specifies the chain to be importing funds from. -// // - [to] specifies where to send the imported funds to. -// // - [baseFee] specifies the fee price willing to be paid by this tx. -// NewImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedImportTx, error) - -// // NewExportTx creates an export transaction that attempts to send all the -// // provided [outputs] to the requested [chainID]. -// // -// // - [chainID] specifies the chain to be exporting the funds to. -// // - [outputs] specifies the outputs to send to the [chainID]. -// // - [baseFee] specifies the fee price willing to be paid by this tx. -// NewExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedExportTx, error) -// } - -// // BuilderBackend specifies the required information needed to build unsigned -// // C-chain transactions. -// type BuilderBackend interface { -// Context - -// UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) -// Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) -// Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) -// } - -// type builder struct { -// avaxAddrs set.Set[ids.ShortID] -// ethAddrs set.Set[ethcommon.Address] -// backend BuilderBackend -// } - -// // NewBuilder returns a new transaction builder. -// // -// // - [avaxAddrs] is the set of addresses in the AVAX format that the builder -// // assumes can be used when signing the transactions in the future. -// // - [ethAddrs] is the set of addresses in the Eth format that the builder -// // assumes can be used when signing the transactions in the future. -// // - [backend] provides the required access to the chain's context and state -// // to build out the transactions. -// func NewBuilder( -// avaxAddrs set.Set[ids.ShortID], -// ethAddrs set.Set[ethcommon.Address], -// backend BuilderBackend, -// ) Builder { -// return &builder{ -// avaxAddrs: avaxAddrs, -// ethAddrs: ethAddrs, -// backend: backend, -// } -// } - -// func (b *builder) GetBalance( -// options ...common.Option, -// ) (*big.Int, error) { -// var ( -// ops = common.NewOptions(options) -// ctx = ops.Context() -// addrs = ops.EthAddresses(b.ethAddrs) -// totalBalance = new(big.Int) -// ) -// for addr := range addrs { -// balance, err := b.backend.Balance(ctx, addr) -// if err != nil { -// return nil, err -// } -// totalBalance.Add(totalBalance, balance) -// } - -// return totalBalance, nil -// } - -// func (b *builder) GetImportableBalance( -// chainID ids.ID, -// options ...common.Option, -// ) (uint64, error) { -// ops := common.NewOptions(options) -// utxos, err := b.backend.UTXOs(ops.Context(), chainID) -// if err != nil { -// return 0, err -// } - -// var ( -// addrs = ops.Addresses(b.avaxAddrs) -// minIssuanceTime = ops.MinIssuanceTime() -// avaxAssetID = b.backend.AVAXAssetID() -// balance uint64 -// ) -// for _, utxo := range utxos { -// amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) -// if !ok { -// continue -// } - -// newBalance, err := math.Add64(balance, amount) -// if err != nil { -// return 0, err -// } -// balance = newBalance -// } - -// return balance, nil -// } - -// func (b *builder) NewImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedImportTx, error) { -// ops := common.NewOptions(options) -// utxos, err := b.backend.UTXOs(ops.Context(), chainID) -// if err != nil { -// return nil, err -// } - -// var ( -// addrs = ops.Addresses(b.avaxAddrs) -// minIssuanceTime = ops.MinIssuanceTime() -// avaxAssetID = b.backend.AVAXAssetID() - -// importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) -// importedAmount uint64 -// ) -// for _, utxo := range utxos { -// amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) -// if !ok { -// continue -// } - -// importedInputs = append(importedInputs, &avax.TransferableInput{ -// UTXOID: utxo.UTXOID, -// Asset: utxo.Asset, -// In: &secp256k1fx.TransferInput{ -// Amt: amount, -// Input: secp256k1fx.Input{ -// SigIndices: inputSigIndices, -// }, -// }, -// }) - -// newImportedAmount, err := math.Add64(importedAmount, amount) -// if err != nil { -// return nil, err -// } -// importedAmount = newImportedAmount -// } - -// utils.Sort(importedInputs) -// tx := &evm.UnsignedImportTx{ -// NetworkID: b.backend.NetworkID(), -// BlockchainID: b.backend.BlockchainID(), -// SourceChain: chainID, -// ImportedInputs: importedInputs, -// } - -// // We must initialize the bytes of the tx to calculate the initial cost -// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} -// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { -// return nil, err -// } - -// gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) -// if err != nil { -// return nil, err -// } -// gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas - -// txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) -// if err != nil { -// return nil, err -// } - -// if importedAmount <= txFee { -// return nil, errInsufficientFunds -// } - -// tx.Outs = []evm.EVMOutput{{ -// Address: to, -// Amount: importedAmount - txFee, -// AssetID: avaxAssetID, -// }} -// return tx, nil -// } - -// func (b *builder) NewExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedExportTx, error) { -// var ( -// avaxAssetID = b.backend.AVAXAssetID() -// exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) -// exportedAmount uint64 -// ) -// for i, output := range outputs { -// exportedOutputs[i] = &avax.TransferableOutput{ -// Asset: avax.Asset{ID: avaxAssetID}, -// Out: output, -// } - -// newExportedAmount, err := math.Add64(exportedAmount, output.Amt) -// if err != nil { -// return nil, err -// } -// exportedAmount = newExportedAmount -// } - -// avax.SortTransferableOutputs(exportedOutputs, evm.Codec) -// tx := &evm.UnsignedExportTx{ -// NetworkID: b.backend.NetworkID(), -// BlockchainID: b.backend.BlockchainID(), -// DestinationChain: chainID, -// ExportedOutputs: exportedOutputs, -// } - -// // We must initialize the bytes of the tx to calculate the initial cost -// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} -// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { -// return nil, err -// } - -// cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) -// if err != nil { -// return nil, err -// } - -// initialFee, err := evm.CalculateDynamicFee(cost, baseFee) -// if err != nil { -// return nil, err -// } - -// amountToConsume, err := math.Add64(exportedAmount, initialFee) -// if err != nil { -// return nil, err -// } - -// var ( -// ops = common.NewOptions(options) -// ctx = ops.Context() -// addrs = ops.EthAddresses(b.ethAddrs) -// inputs = make([]evm.EVMInput, 0, addrs.Len()) -// ) -// for addr := range addrs { -// if amountToConsume == 0 { -// break -// } - -// prevFee, err := evm.CalculateDynamicFee(cost, baseFee) -// if err != nil { -// return nil, err -// } - -// newCost := cost + evm.EVMInputGas -// newFee, err := evm.CalculateDynamicFee(newCost, baseFee) -// if err != nil { -// return nil, err -// } - -// additionalFee := newFee - prevFee - -// balance, err := b.backend.Balance(ctx, addr) -// if err != nil { -// return nil, err -// } - -// // Since the asset is AVAX, we divide by the avaxConversionRate to -// // convert back to the correct denomination of AVAX that can be -// // exported. -// avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() - -// // If the balance for [addr] is insufficient to cover the additional -// // cost of adding an input to the transaction, skip adding the input -// // altogether. -// if avaxBalance <= additionalFee { -// continue -// } - -// // Update the cost for the next iteration -// cost = newCost - -// amountToConsume, err = math.Add64(amountToConsume, additionalFee) -// if err != nil { -// return nil, err -// } - -// nonce, err := b.backend.Nonce(ctx, addr) -// if err != nil { -// return nil, err -// } - -// inputAmount := math.Min(amountToConsume, avaxBalance) -// inputs = append(inputs, evm.EVMInput{ -// Address: addr, -// Amount: inputAmount, -// AssetID: avaxAssetID, -// Nonce: nonce, -// }) -// amountToConsume -= inputAmount -// } - -// if amountToConsume > 0 { -// return nil, errInsufficientFunds -// } - -// utils.Sort(inputs) -// tx.Ins = inputs -// return tx, nil -// } - -// func getSpendableAmount( -// utxo *avax.UTXO, -// addrs set.Set[ids.ShortID], -// minIssuanceTime uint64, -// avaxAssetID ids.ID, -// ) (uint64, []uint32, bool) { -// if utxo.Asset.ID != avaxAssetID { -// // Only AVAX can be imported -// return 0, nil, false -// } - -// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) -// if !ok { -// // Can't import an unknown transfer output type -// return 0, nil, false -// } - -// inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) -// return out.Amt, inputSigIndices, ok -// } +import ( + "errors" + "math/big" + + stdcontext "context" + + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils" + "github.com/ava-labs/avalanchego/utils/math" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +const avaxConversionRateInt = 1_000_000_000 + +var ( + _ Builder = (*builder)(nil) + + errInsufficientFunds = errors.New("insufficient funds") + + // avaxConversionRate is the conversion rate between the smallest + // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest + // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. + // + // This is only required for AVAX because the denomination of 1 AVAX is 9 + // decimal places on the X and P chains, but is 18 decimal places within the + // EVM. + avaxConversionRate = big.NewInt(avaxConversionRateInt) +) + +// Builder provides a convenient interface for building unsigned C-chain +// transactions. +type Builder interface { + // GetBalance calculates the amount of AVAX that this builder has control + // over. + GetBalance( + options ...common.Option, + ) (*big.Int, error) + + // GetImportableBalance calculates the amount of AVAX that this builder + // could import from the provided chain. + // + // - [chainID] specifies the chain the funds are from. + GetImportableBalance( + chainID ids.ID, + options ...common.Option, + ) (uint64, error) + + // NewImportTx creates an import transaction that attempts to consume all + // the available UTXOs and import the funds to [to]. + // + // - [chainID] specifies the chain to be importing funds from. + // - [to] specifies where to send the imported funds to. + // - [baseFee] specifies the fee price willing to be paid by this tx. + NewImportTx( + chainID ids.ID, + to ethcommon.Address, + baseFee *big.Int, + options ...common.Option, + ) (*evm.UnsignedImportTx, error) + + // NewExportTx creates an export transaction that attempts to send all the + // provided [outputs] to the requested [chainID]. + // + // - [chainID] specifies the chain to be exporting the funds to. + // - [outputs] specifies the outputs to send to the [chainID]. + // - [baseFee] specifies the fee price willing to be paid by this tx. + NewExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + baseFee *big.Int, + options ...common.Option, + ) (*evm.UnsignedExportTx, error) +} + +// BuilderBackend specifies the required information needed to build unsigned +// C-chain transactions. +type BuilderBackend interface { + Context + + UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) + Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) + Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) +} + +type builder struct { + avaxAddrs set.Set[ids.ShortID] + ethAddrs set.Set[ethcommon.Address] + backend BuilderBackend +} + +// NewBuilder returns a new transaction builder. +// +// - [avaxAddrs] is the set of addresses in the AVAX format that the builder +// assumes can be used when signing the transactions in the future. +// - [ethAddrs] is the set of addresses in the Eth format that the builder +// assumes can be used when signing the transactions in the future. +// - [backend] provides the required access to the chain's context and state +// to build out the transactions. +func NewBuilder( + avaxAddrs set.Set[ids.ShortID], + ethAddrs set.Set[ethcommon.Address], + backend BuilderBackend, +) Builder { + return &builder{ + avaxAddrs: avaxAddrs, + ethAddrs: ethAddrs, + backend: backend, + } +} + +func (b *builder) GetBalance( + options ...common.Option, +) (*big.Int, error) { + var ( + ops = common.NewOptions(options) + ctx = ops.Context() + addrs = ops.EthAddresses(b.ethAddrs) + totalBalance = new(big.Int) + ) + for addr := range addrs { + balance, err := b.backend.Balance(ctx, addr) + if err != nil { + return nil, err + } + totalBalance.Add(totalBalance, balance) + } + + return totalBalance, nil +} + +func (b *builder) GetImportableBalance( + chainID ids.ID, + options ...common.Option, +) (uint64, error) { + ops := common.NewOptions(options) + utxos, err := b.backend.UTXOs(ops.Context(), chainID) + if err != nil { + return 0, err + } + + var ( + addrs = ops.Addresses(b.avaxAddrs) + minIssuanceTime = ops.MinIssuanceTime() + avaxAssetID = b.backend.AVAXAssetID() + balance uint64 + ) + for _, utxo := range utxos { + amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) + if !ok { + continue + } + + newBalance, err := math.Add64(balance, amount) + if err != nil { + return 0, err + } + balance = newBalance + } + + return balance, nil +} + +func (b *builder) NewImportTx( + chainID ids.ID, + to ethcommon.Address, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedImportTx, error) { + ops := common.NewOptions(options) + utxos, err := b.backend.UTXOs(ops.Context(), chainID) + if err != nil { + return nil, err + } + + var ( + addrs = ops.Addresses(b.avaxAddrs) + minIssuanceTime = ops.MinIssuanceTime() + avaxAssetID = b.backend.AVAXAssetID() + + importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) + importedAmount uint64 + ) + for _, utxo := range utxos { + amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) + if !ok { + continue + } + + importedInputs = append(importedInputs, &avax.TransferableInput{ + UTXOID: utxo.UTXOID, + Asset: utxo.Asset, + In: &secp256k1fx.TransferInput{ + Amt: amount, + Input: secp256k1fx.Input{ + SigIndices: inputSigIndices, + }, + }, + }) + + newImportedAmount, err := math.Add64(importedAmount, amount) + if err != nil { + return nil, err + } + importedAmount = newImportedAmount + } + + utils.Sort(importedInputs) + tx := &evm.UnsignedImportTx{ + NetworkID: b.backend.NetworkID(), + BlockchainID: b.backend.BlockchainID(), + SourceChain: chainID, + ImportedInputs: importedInputs, + } + + // We must initialize the bytes of the tx to calculate the initial cost + wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} + if err := wrappedTx.Sign(evm.Codec, nil); err != nil { + return nil, err + } + + gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) + if err != nil { + return nil, err + } + gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas + + txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) + if err != nil { + return nil, err + } + + if importedAmount <= txFee { + return nil, errInsufficientFunds + } + + tx.Outs = []evm.EVMOutput{{ + Address: to, + Amount: importedAmount - txFee, + AssetID: avaxAssetID, + }} + return tx, nil +} + +func (b *builder) NewExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedExportTx, error) { + var ( + avaxAssetID = b.backend.AVAXAssetID() + exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) + exportedAmount uint64 + ) + for i, output := range outputs { + exportedOutputs[i] = &avax.TransferableOutput{ + Asset: avax.Asset{ID: avaxAssetID}, + Out: output, + } + + newExportedAmount, err := math.Add64(exportedAmount, output.Amt) + if err != nil { + return nil, err + } + exportedAmount = newExportedAmount + } + + avax.SortTransferableOutputs(exportedOutputs, evm.Codec) + tx := &evm.UnsignedExportTx{ + NetworkID: b.backend.NetworkID(), + BlockchainID: b.backend.BlockchainID(), + DestinationChain: chainID, + ExportedOutputs: exportedOutputs, + } + + // We must initialize the bytes of the tx to calculate the initial cost + wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} + if err := wrappedTx.Sign(evm.Codec, nil); err != nil { + return nil, err + } + + cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) + if err != nil { + return nil, err + } + + initialFee, err := evm.CalculateDynamicFee(cost, baseFee) + if err != nil { + return nil, err + } + + amountToConsume, err := math.Add64(exportedAmount, initialFee) + if err != nil { + return nil, err + } + + var ( + ops = common.NewOptions(options) + ctx = ops.Context() + addrs = ops.EthAddresses(b.ethAddrs) + inputs = make([]evm.EVMInput, 0, addrs.Len()) + ) + for addr := range addrs { + if amountToConsume == 0 { + break + } + + prevFee, err := evm.CalculateDynamicFee(cost, baseFee) + if err != nil { + return nil, err + } + + newCost := cost + evm.EVMInputGas + newFee, err := evm.CalculateDynamicFee(newCost, baseFee) + if err != nil { + return nil, err + } + + additionalFee := newFee - prevFee + + balance, err := b.backend.Balance(ctx, addr) + if err != nil { + return nil, err + } + + // Since the asset is AVAX, we divide by the avaxConversionRate to + // convert back to the correct denomination of AVAX that can be + // exported. + avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() + + // If the balance for [addr] is insufficient to cover the additional + // cost of adding an input to the transaction, skip adding the input + // altogether. + if avaxBalance <= additionalFee { + continue + } + + // Update the cost for the next iteration + cost = newCost + + amountToConsume, err = math.Add64(amountToConsume, additionalFee) + if err != nil { + return nil, err + } + + nonce, err := b.backend.Nonce(ctx, addr) + if err != nil { + return nil, err + } + + inputAmount := math.Min(amountToConsume, avaxBalance) + inputs = append(inputs, evm.EVMInput{ + Address: addr, + Amount: inputAmount, + AssetID: avaxAssetID, + Nonce: nonce, + }) + amountToConsume -= inputAmount + } + + if amountToConsume > 0 { + return nil, errInsufficientFunds + } + + utils.Sort(inputs) + tx.Ins = inputs + return tx, nil +} + +func getSpendableAmount( + utxo *avax.UTXO, + addrs set.Set[ids.ShortID], + minIssuanceTime uint64, + avaxAssetID ids.ID, +) (uint64, []uint32, bool) { + if utxo.Asset.ID != avaxAssetID { + // Only AVAX can be imported + return 0, nil, false + } + + out, ok := utxo.Out.(*secp256k1fx.TransferOutput) + if !ok { + // Can't import an unknown transfer output type + return 0, nil, false + } + + inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) + return out.Amt, inputSigIndices, ok +} diff --git a/wallet/chain/c/builder_with_options.go b/wallet/chain/c/builder_with_options.go index 9b7ab8399484..8416dddf9928 100644 --- a/wallet/chain/c/builder_with_options.go +++ b/wallet/chain/c/builder_with_options.go @@ -3,81 +3,81 @@ package c -// import ( -// "math/big" +import ( + "math/big" -// "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/coreth/plugin/evm" -// ethcommon "github.com/ethereum/go-ethereum/common" + ethcommon "github.com/ethereum/go-ethereum/common" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) -// var _ Builder = (*builderWithOptions)(nil) +var _ Builder = (*builderWithOptions)(nil) -// type builderWithOptions struct { -// Builder -// options []common.Option -// } +type builderWithOptions struct { + Builder + options []common.Option +} -// // NewBuilderWithOptions returns a new transaction builder that will use the -// // given options by default. -// // -// // - [builder] is the builder that will be called to perform the underlying -// // operations. -// // - [options] will be provided to the builder in addition to the options -// // provided in the method calls. -// func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { -// return &builderWithOptions{ -// Builder: builder, -// options: options, -// } -// } +// NewBuilderWithOptions returns a new transaction builder that will use the +// given options by default. +// +// - [builder] is the builder that will be called to perform the underlying +// operations. +// - [options] will be provided to the builder in addition to the options +// provided in the method calls. +func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { + return &builderWithOptions{ + Builder: builder, + options: options, + } +} -// func (b *builderWithOptions) GetBalance( -// options ...common.Option, -// ) (*big.Int, error) { -// return b.Builder.GetBalance( -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) GetBalance( + options ...common.Option, +) (*big.Int, error) { + return b.Builder.GetBalance( + common.UnionOptions(b.options, options)..., + ) +} -// func (b *builderWithOptions) GetImportableBalance( -// chainID ids.ID, -// options ...common.Option, -// ) (uint64, error) { -// return b.Builder.GetImportableBalance( -// chainID, -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) GetImportableBalance( + chainID ids.ID, + options ...common.Option, +) (uint64, error) { + return b.Builder.GetImportableBalance( + chainID, + common.UnionOptions(b.options, options)..., + ) +} -// func (b *builderWithOptions) NewImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedImportTx, error) { -// return b.Builder.NewImportTx( -// chainID, -// to, -// baseFee, -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) NewImportTx( + chainID ids.ID, + to ethcommon.Address, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedImportTx, error) { + return b.Builder.NewImportTx( + chainID, + to, + baseFee, + common.UnionOptions(b.options, options)..., + ) +} -// func (b *builderWithOptions) NewExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedExportTx, error) { -// return b.Builder.NewExportTx( -// chainID, -// outputs, -// baseFee, -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) NewExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedExportTx, error) { + return b.Builder.NewExportTx( + chainID, + outputs, + baseFee, + common.UnionOptions(b.options, options)..., + ) +} diff --git a/wallet/chain/c/context.go b/wallet/chain/c/context.go index 1c01d8fb55c8..d506b42f81fa 100644 --- a/wallet/chain/c/context.go +++ b/wallet/chain/c/context.go @@ -3,81 +3,81 @@ package c -// import ( -// stdcontext "context" +import ( + stdcontext "context" -// "github.com/ava-labs/avalanchego/api/info" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/avm" -// ) + "github.com/ava-labs/avalanchego/api/info" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/avm" +) -// var _ Context = (*context)(nil) +var _ Context = (*context)(nil) -// type Context interface { -// NetworkID() uint32 -// BlockchainID() ids.ID -// AVAXAssetID() ids.ID -// } +type Context interface { + NetworkID() uint32 + BlockchainID() ids.ID + AVAXAssetID() ids.ID +} -// type context struct { -// networkID uint32 -// blockchainID ids.ID -// avaxAssetID ids.ID -// } +type context struct { + networkID uint32 + blockchainID ids.ID + avaxAssetID ids.ID +} -// func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { -// infoClient := info.NewClient(uri) -// xChainClient := avm.NewClient(uri, "X") -// return NewContextFromClients(ctx, infoClient, xChainClient) -// } +func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { + infoClient := info.NewClient(uri) + xChainClient := avm.NewClient(uri, "X") + return NewContextFromClients(ctx, infoClient, xChainClient) +} -// func NewContextFromClients( -// ctx stdcontext.Context, -// infoClient info.Client, -// xChainClient avm.Client, -// ) (Context, error) { -// networkID, err := infoClient.GetNetworkID(ctx) -// if err != nil { -// return nil, err -// } +func NewContextFromClients( + ctx stdcontext.Context, + infoClient info.Client, + xChainClient avm.Client, +) (Context, error) { + networkID, err := infoClient.GetNetworkID(ctx) + if err != nil { + return nil, err + } -// chainID, err := infoClient.GetBlockchainID(ctx, "C") -// if err != nil { -// return nil, err -// } + chainID, err := infoClient.GetBlockchainID(ctx, "C") + if err != nil { + return nil, err + } -// asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") -// if err != nil { -// return nil, err -// } + asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") + if err != nil { + return nil, err + } -// return NewContext( -// networkID, -// chainID, -// asset.AssetID, -// ), nil -// } + return NewContext( + networkID, + chainID, + asset.AssetID, + ), nil +} -// func NewContext( -// networkID uint32, -// blockchainID ids.ID, -// avaxAssetID ids.ID, -// ) Context { -// return &context{ -// networkID: networkID, -// blockchainID: blockchainID, -// avaxAssetID: avaxAssetID, -// } -// } +func NewContext( + networkID uint32, + blockchainID ids.ID, + avaxAssetID ids.ID, +) Context { + return &context{ + networkID: networkID, + blockchainID: blockchainID, + avaxAssetID: avaxAssetID, + } +} -// func (c *context) NetworkID() uint32 { -// return c.networkID -// } +func (c *context) NetworkID() uint32 { + return c.networkID +} -// func (c *context) BlockchainID() ids.ID { -// return c.blockchainID -// } +func (c *context) BlockchainID() ids.ID { + return c.blockchainID +} -// func (c *context) AVAXAssetID() ids.ID { -// return c.avaxAssetID -// } +func (c *context) AVAXAssetID() ids.ID { + return c.avaxAssetID +} diff --git a/wallet/chain/c/signer.go b/wallet/chain/c/signer.go index 4bedc378234b..4fd85ed3b532 100644 --- a/wallet/chain/c/signer.go +++ b/wallet/chain/c/signer.go @@ -3,221 +3,221 @@ package c -// import ( -// "errors" -// "fmt" - -// stdcontext "context" - -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/database" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils/crypto/keychain" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/hashing" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/components/verify" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// ) - -// const version = 0 - -// var ( -// _ Signer = (*txSigner)(nil) - -// errUnknownInputType = errors.New("unknown input type") -// errUnknownCredentialType = errors.New("unknown credential type") -// errUnknownOutputType = errors.New("unknown output type") -// errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") - -// emptySig [secp256k1.SignatureLen]byte -// ) - -// type Signer interface { -// SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) -// SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error -// } - -// type EthKeychain interface { -// // The returned Signer can provide a signature for [addr] -// GetEth(addr ethcommon.Address) (keychain.Signer, bool) -// // Returns the set of addresses for which the accessor keeps an associated -// // signer -// EthAddresses() set.Set[ethcommon.Address] -// } - -// type SignerBackend interface { -// GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) -// } - -// type txSigner struct { -// avaxKC keychain.Keychain -// ethKC EthKeychain -// backend SignerBackend -// } - -// func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { -// return &txSigner{ -// avaxKC: avaxKC, -// ethKC: ethKC, -// backend: backend, -// } -// } - -// func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { -// tx := &evm.Tx{UnsignedAtomicTx: utx} -// return tx, s.SignAtomic(ctx, tx) -// } - -// func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { -// switch utx := tx.UnsignedAtomicTx.(type) { -// case *evm.UnsignedImportTx: -// signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) -// if err != nil { -// return err -// } -// return sign(tx, true, signers) -// case *evm.UnsignedExportTx: -// signers := s.getExportSigners(utx.Ins) -// return sign(tx, true, signers) -// default: -// return fmt.Errorf("%w: %T", errUnknownTxType, tx) -// } -// } - -// func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { -// txSigners := make([][]keychain.Signer, len(ins)) -// for credIndex, transferInput := range ins { -// input, ok := transferInput.In.(*secp256k1fx.TransferInput) -// if !ok { -// return nil, errUnknownInputType -// } - -// inputSigners := make([]keychain.Signer, len(input.SigIndices)) -// txSigners[credIndex] = inputSigners - -// utxoID := transferInput.InputID() -// utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) -// if err == database.ErrNotFound { -// // If we don't have access to the UTXO, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// if err != nil { -// return nil, err -// } - -// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) -// if !ok { -// return nil, errUnknownOutputType -// } - -// for sigIndex, addrIndex := range input.SigIndices { -// if addrIndex >= uint32(len(out.Addrs)) { -// return nil, errInvalidUTXOSigIndex -// } - -// addr := out.Addrs[addrIndex] -// key, ok := s.avaxKC.Get(addr) -// if !ok { -// // If we don't have access to the key, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// inputSigners[sigIndex] = key -// } -// } -// return txSigners, nil -// } - -// func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { -// txSigners := make([][]keychain.Signer, len(ins)) -// for credIndex, input := range ins { -// inputSigners := make([]keychain.Signer, 1) -// txSigners[credIndex] = inputSigners - -// key, ok := s.ethKC.GetEth(input.Address) -// if !ok { -// // If we don't have access to the key, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// inputSigners[0] = key -// } -// return txSigners -// } - -// // TODO: remove [signHash] after the ledger supports signing all transactions. -// func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { -// unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) -// if err != nil { -// return fmt.Errorf("couldn't marshal unsigned tx: %w", err) -// } -// unsignedHash := hashing.ComputeHash256(unsignedBytes) - -// if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { -// tx.Creds = make([]verify.Verifiable, expectedLen) -// } - -// sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) -// for credIndex, inputSigners := range txSigners { -// credIntf := tx.Creds[credIndex] -// if credIntf == nil { -// credIntf = &secp256k1fx.Credential{} -// tx.Creds[credIndex] = credIntf -// } - -// cred, ok := credIntf.(*secp256k1fx.Credential) -// if !ok { -// return errUnknownCredentialType -// } -// if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { -// cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) -// } - -// for sigIndex, signer := range inputSigners { -// if signer == nil { -// // If we don't have access to the key, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// addr := signer.Address() -// if sig := cred.Sigs[sigIndex]; sig != emptySig { -// // If this signature has already been populated, we can just -// // copy the needed signature for the future. -// sigCache[addr] = sig -// continue -// } - -// if sig, exists := sigCache[addr]; exists { -// // If this key has already produced a signature, we can just -// // copy the previous signature. -// cred.Sigs[sigIndex] = sig -// continue -// } - -// var sig []byte -// if signHash { -// sig, err = signer.SignHash(unsignedHash) -// } else { -// sig, err = signer.Sign(unsignedBytes) -// } -// if err != nil { -// return fmt.Errorf("problem signing tx: %w", err) -// } -// copy(cred.Sigs[sigIndex][:], sig) -// sigCache[addr] = cred.Sigs[sigIndex] -// } -// } - -// signedBytes, err := evm.Codec.Marshal(version, tx) -// if err != nil { -// return fmt.Errorf("couldn't marshal tx: %w", err) -// } -// tx.Initialize(unsignedBytes, signedBytes) -// return nil -// } +import ( + "errors" + "fmt" + + stdcontext "context" + + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/crypto/keychain" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/hashing" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/components/verify" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" +) + +const version = 0 + +var ( + _ Signer = (*txSigner)(nil) + + errUnknownInputType = errors.New("unknown input type") + errUnknownCredentialType = errors.New("unknown credential type") + errUnknownOutputType = errors.New("unknown output type") + errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") + + emptySig [secp256k1.SignatureLen]byte +) + +type Signer interface { + SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) + SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error +} + +type EthKeychain interface { + // The returned Signer can provide a signature for [addr] + GetEth(addr ethcommon.Address) (keychain.Signer, bool) + // Returns the set of addresses for which the accessor keeps an associated + // signer + EthAddresses() set.Set[ethcommon.Address] +} + +type SignerBackend interface { + GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) +} + +type txSigner struct { + avaxKC keychain.Keychain + ethKC EthKeychain + backend SignerBackend +} + +func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { + return &txSigner{ + avaxKC: avaxKC, + ethKC: ethKC, + backend: backend, + } +} + +func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { + tx := &evm.Tx{UnsignedAtomicTx: utx} + return tx, s.SignAtomic(ctx, tx) +} + +func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { + switch utx := tx.UnsignedAtomicTx.(type) { + case *evm.UnsignedImportTx: + signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) + if err != nil { + return err + } + return sign(tx, true, signers) + case *evm.UnsignedExportTx: + signers := s.getExportSigners(utx.Ins) + return sign(tx, true, signers) + default: + return fmt.Errorf("%w: %T", errUnknownTxType, tx) + } +} + +func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { + txSigners := make([][]keychain.Signer, len(ins)) + for credIndex, transferInput := range ins { + input, ok := transferInput.In.(*secp256k1fx.TransferInput) + if !ok { + return nil, errUnknownInputType + } + + inputSigners := make([]keychain.Signer, len(input.SigIndices)) + txSigners[credIndex] = inputSigners + + utxoID := transferInput.InputID() + utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) + if err == database.ErrNotFound { + // If we don't have access to the UTXO, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + if err != nil { + return nil, err + } + + out, ok := utxo.Out.(*secp256k1fx.TransferOutput) + if !ok { + return nil, errUnknownOutputType + } + + for sigIndex, addrIndex := range input.SigIndices { + if addrIndex >= uint32(len(out.Addrs)) { + return nil, errInvalidUTXOSigIndex + } + + addr := out.Addrs[addrIndex] + key, ok := s.avaxKC.Get(addr) + if !ok { + // If we don't have access to the key, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + inputSigners[sigIndex] = key + } + } + return txSigners, nil +} + +func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { + txSigners := make([][]keychain.Signer, len(ins)) + for credIndex, input := range ins { + inputSigners := make([]keychain.Signer, 1) + txSigners[credIndex] = inputSigners + + key, ok := s.ethKC.GetEth(input.Address) + if !ok { + // If we don't have access to the key, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + inputSigners[0] = key + } + return txSigners +} + +// TODO: remove [signHash] after the ledger supports signing all transactions. +func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { + unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) + if err != nil { + return fmt.Errorf("couldn't marshal unsigned tx: %w", err) + } + unsignedHash := hashing.ComputeHash256(unsignedBytes) + + if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { + tx.Creds = make([]verify.Verifiable, expectedLen) + } + + sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) + for credIndex, inputSigners := range txSigners { + credIntf := tx.Creds[credIndex] + if credIntf == nil { + credIntf = &secp256k1fx.Credential{} + tx.Creds[credIndex] = credIntf + } + + cred, ok := credIntf.(*secp256k1fx.Credential) + if !ok { + return errUnknownCredentialType + } + if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { + cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) + } + + for sigIndex, signer := range inputSigners { + if signer == nil { + // If we don't have access to the key, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + addr := signer.Address() + if sig := cred.Sigs[sigIndex]; sig != emptySig { + // If this signature has already been populated, we can just + // copy the needed signature for the future. + sigCache[addr] = sig + continue + } + + if sig, exists := sigCache[addr]; exists { + // If this key has already produced a signature, we can just + // copy the previous signature. + cred.Sigs[sigIndex] = sig + continue + } + + var sig []byte + if signHash { + sig, err = signer.SignHash(unsignedHash) + } else { + sig, err = signer.Sign(unsignedBytes) + } + if err != nil { + return fmt.Errorf("problem signing tx: %w", err) + } + copy(cred.Sigs[sigIndex][:], sig) + sigCache[addr] = cred.Sigs[sigIndex] + } + } + + signedBytes, err := evm.Codec.Marshal(version, tx) + if err != nil { + return fmt.Errorf("couldn't marshal tx: %w", err) + } + tx.Initialize(unsignedBytes, signedBytes) + return nil +} diff --git a/wallet/chain/c/wallet.go b/wallet/chain/c/wallet.go index ebee50a9a958..fb1a83d53dad 100644 --- a/wallet/chain/c/wallet.go +++ b/wallet/chain/c/wallet.go @@ -3,204 +3,204 @@ package c -// import ( -// "errors" -// "math/big" -// "time" - -// "github.com/ava-labs/coreth/ethclient" -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var ( -// _ Wallet = (*wallet)(nil) - -// errNotCommitted = errors.New("not committed") -// ) - -// type Wallet interface { -// Context - -// // Builder returns the builder that will be used to create the transactions. -// Builder() Builder - -// // Signer returns the signer that will be used to sign the transactions. -// Signer() Signer - -// // IssueImportTx creates, signs, and issues an import transaction that -// // attempts to consume all the available UTXOs and import the funds to [to]. -// // -// // - [chainID] specifies the chain to be importing funds from. -// // - [to] specifies where to send the imported funds to. -// IssueImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// options ...common.Option, -// ) (*evm.Tx, error) - -// // IssueExportTx creates, signs, and issues an export transaction that -// // attempts to send all the provided [outputs] to the requested [chainID]. -// // -// // - [chainID] specifies the chain to be exporting the funds to. -// // - [outputs] specifies the outputs to send to the [chainID]. -// IssueExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// options ...common.Option, -// ) (*evm.Tx, error) - -// // IssueUnsignedTx signs and issues the unsigned tx. -// IssueUnsignedAtomicTx( -// utx evm.UnsignedAtomicTx, -// options ...common.Option, -// ) (*evm.Tx, error) - -// // IssueAtomicTx issues the signed tx. -// IssueAtomicTx( -// tx *evm.Tx, -// options ...common.Option, -// ) error -// } - -// func NewWallet( -// builder Builder, -// signer Signer, -// avaxClient evm.Client, -// ethClient ethclient.Client, -// backend Backend, -// ) Wallet { -// return &wallet{ -// Backend: backend, -// builder: builder, -// signer: signer, -// avaxClient: avaxClient, -// ethClient: ethClient, -// } -// } - -// type wallet struct { -// Backend -// builder Builder -// signer Signer -// avaxClient evm.Client -// ethClient ethclient.Client -// } - -// func (w *wallet) Builder() Builder { -// return w.builder -// } - -// func (w *wallet) Signer() Signer { -// return w.signer -// } - -// func (w *wallet) IssueImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// options ...common.Option, -// ) (*evm.Tx, error) { -// baseFee, err := w.baseFee(options) -// if err != nil { -// return nil, err -// } - -// utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) -// if err != nil { -// return nil, err -// } -// return w.IssueUnsignedAtomicTx(utx, options...) -// } - -// func (w *wallet) IssueExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// options ...common.Option, -// ) (*evm.Tx, error) { -// baseFee, err := w.baseFee(options) -// if err != nil { -// return nil, err -// } - -// utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) -// if err != nil { -// return nil, err -// } -// return w.IssueUnsignedAtomicTx(utx, options...) -// } - -// func (w *wallet) IssueUnsignedAtomicTx( -// utx evm.UnsignedAtomicTx, -// options ...common.Option, -// ) (*evm.Tx, error) { -// ops := common.NewOptions(options) -// ctx := ops.Context() -// tx, err := w.signer.SignUnsignedAtomic(ctx, utx) -// if err != nil { -// return nil, err -// } - -// return tx, w.IssueAtomicTx(tx, options...) -// } - -// func (w *wallet) IssueAtomicTx( -// tx *evm.Tx, -// options ...common.Option, -// ) error { -// ops := common.NewOptions(options) -// ctx := ops.Context() -// txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) -// if err != nil { -// return err -// } - -// if f := ops.PostIssuanceFunc(); f != nil { -// f(txID) -// } - -// if ops.AssumeDecided() { -// return w.Backend.AcceptAtomicTx(ctx, tx) -// } - -// pollFrequency := ops.PollFrequency() -// ticker := time.NewTicker(pollFrequency) -// defer ticker.Stop() - -// for { -// status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) -// if err != nil { -// return err -// } - -// switch status { -// case evm.Accepted: -// return w.Backend.AcceptAtomicTx(ctx, tx) -// case evm.Dropped, evm.Unknown: -// return errNotCommitted -// } - -// // The tx is Processing. - -// select { -// case <-ticker.C: -// case <-ctx.Done(): -// return ctx.Err() -// } -// } -// } - -// func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { -// ops := common.NewOptions(options) -// baseFee := ops.BaseFee(nil) -// if baseFee != nil { -// return baseFee, nil -// } - -// ctx := ops.Context() -// return w.ethClient.EstimateBaseFee(ctx) -// } +import ( + "errors" + "math/big" + "time" + + "github.com/ava-labs/coreth/ethclient" + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var ( + _ Wallet = (*wallet)(nil) + + errNotCommitted = errors.New("not committed") +) + +type Wallet interface { + Context + + // Builder returns the builder that will be used to create the transactions. + Builder() Builder + + // Signer returns the signer that will be used to sign the transactions. + Signer() Signer + + // IssueImportTx creates, signs, and issues an import transaction that + // attempts to consume all the available UTXOs and import the funds to [to]. + // + // - [chainID] specifies the chain to be importing funds from. + // - [to] specifies where to send the imported funds to. + IssueImportTx( + chainID ids.ID, + to ethcommon.Address, + options ...common.Option, + ) (*evm.Tx, error) + + // IssueExportTx creates, signs, and issues an export transaction that + // attempts to send all the provided [outputs] to the requested [chainID]. + // + // - [chainID] specifies the chain to be exporting the funds to. + // - [outputs] specifies the outputs to send to the [chainID]. + IssueExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + options ...common.Option, + ) (*evm.Tx, error) + + // IssueUnsignedTx signs and issues the unsigned tx. + IssueUnsignedAtomicTx( + utx evm.UnsignedAtomicTx, + options ...common.Option, + ) (*evm.Tx, error) + + // IssueAtomicTx issues the signed tx. + IssueAtomicTx( + tx *evm.Tx, + options ...common.Option, + ) error +} + +func NewWallet( + builder Builder, + signer Signer, + avaxClient evm.Client, + ethClient ethclient.Client, + backend Backend, +) Wallet { + return &wallet{ + Backend: backend, + builder: builder, + signer: signer, + avaxClient: avaxClient, + ethClient: ethClient, + } +} + +type wallet struct { + Backend + builder Builder + signer Signer + avaxClient evm.Client + ethClient ethclient.Client +} + +func (w *wallet) Builder() Builder { + return w.builder +} + +func (w *wallet) Signer() Signer { + return w.signer +} + +func (w *wallet) IssueImportTx( + chainID ids.ID, + to ethcommon.Address, + options ...common.Option, +) (*evm.Tx, error) { + baseFee, err := w.baseFee(options) + if err != nil { + return nil, err + } + + utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) + if err != nil { + return nil, err + } + return w.IssueUnsignedAtomicTx(utx, options...) +} + +func (w *wallet) IssueExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + options ...common.Option, +) (*evm.Tx, error) { + baseFee, err := w.baseFee(options) + if err != nil { + return nil, err + } + + utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) + if err != nil { + return nil, err + } + return w.IssueUnsignedAtomicTx(utx, options...) +} + +func (w *wallet) IssueUnsignedAtomicTx( + utx evm.UnsignedAtomicTx, + options ...common.Option, +) (*evm.Tx, error) { + ops := common.NewOptions(options) + ctx := ops.Context() + tx, err := w.signer.SignUnsignedAtomic(ctx, utx) + if err != nil { + return nil, err + } + + return tx, w.IssueAtomicTx(tx, options...) +} + +func (w *wallet) IssueAtomicTx( + tx *evm.Tx, + options ...common.Option, +) error { + ops := common.NewOptions(options) + ctx := ops.Context() + txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) + if err != nil { + return err + } + + if f := ops.PostIssuanceFunc(); f != nil { + f(txID) + } + + if ops.AssumeDecided() { + return w.Backend.AcceptAtomicTx(ctx, tx) + } + + pollFrequency := ops.PollFrequency() + ticker := time.NewTicker(pollFrequency) + defer ticker.Stop() + + for { + status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) + if err != nil { + return err + } + + switch status { + case evm.Accepted: + return w.Backend.AcceptAtomicTx(ctx, tx) + case evm.Dropped, evm.Unknown: + return errNotCommitted + } + + // The tx is Processing. + + select { + case <-ticker.C: + case <-ctx.Done(): + return ctx.Err() + } + } +} + +func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { + ops := common.NewOptions(options) + baseFee := ops.BaseFee(nil) + if baseFee != nil { + return baseFee, nil + } + + ctx := ops.Context() + return w.ethClient.EstimateBaseFee(ctx) +} diff --git a/wallet/chain/c/wallet_with_options.go b/wallet/chain/c/wallet_with_options.go index fd69a6d4fd02..7d6193683d49 100644 --- a/wallet/chain/c/wallet_with_options.go +++ b/wallet/chain/c/wallet_with_options.go @@ -3,80 +3,80 @@ package c -// import ( -// "github.com/ava-labs/coreth/plugin/evm" +import ( + "github.com/ava-labs/coreth/plugin/evm" -// ethcommon "github.com/ethereum/go-ethereum/common" + ethcommon "github.com/ethereum/go-ethereum/common" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) -// var _ Wallet = (*walletWithOptions)(nil) +var _ Wallet = (*walletWithOptions)(nil) -// func NewWalletWithOptions( -// wallet Wallet, -// options ...common.Option, -// ) Wallet { -// return &walletWithOptions{ -// Wallet: wallet, -// options: options, -// } -// } +func NewWalletWithOptions( + wallet Wallet, + options ...common.Option, +) Wallet { + return &walletWithOptions{ + Wallet: wallet, + options: options, + } +} -// type walletWithOptions struct { -// Wallet -// options []common.Option -// } +type walletWithOptions struct { + Wallet + options []common.Option +} -// func (w *walletWithOptions) Builder() Builder { -// return NewBuilderWithOptions( -// w.Wallet.Builder(), -// w.options..., -// ) -// } +func (w *walletWithOptions) Builder() Builder { + return NewBuilderWithOptions( + w.Wallet.Builder(), + w.options..., + ) +} -// func (w *walletWithOptions) IssueImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// options ...common.Option, -// ) (*evm.Tx, error) { -// return w.Wallet.IssueImportTx( -// chainID, -// to, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueImportTx( + chainID ids.ID, + to ethcommon.Address, + options ...common.Option, +) (*evm.Tx, error) { + return w.Wallet.IssueImportTx( + chainID, + to, + common.UnionOptions(w.options, options)..., + ) +} -// func (w *walletWithOptions) IssueExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// options ...common.Option, -// ) (*evm.Tx, error) { -// return w.Wallet.IssueExportTx( -// chainID, -// outputs, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + options ...common.Option, +) (*evm.Tx, error) { + return w.Wallet.IssueExportTx( + chainID, + outputs, + common.UnionOptions(w.options, options)..., + ) +} -// func (w *walletWithOptions) IssueUnsignedAtomicTx( -// utx evm.UnsignedAtomicTx, -// options ...common.Option, -// ) (*evm.Tx, error) { -// return w.Wallet.IssueUnsignedAtomicTx( -// utx, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueUnsignedAtomicTx( + utx evm.UnsignedAtomicTx, + options ...common.Option, +) (*evm.Tx, error) { + return w.Wallet.IssueUnsignedAtomicTx( + utx, + common.UnionOptions(w.options, options)..., + ) +} -// func (w *walletWithOptions) IssueAtomicTx( -// tx *evm.Tx, -// options ...common.Option, -// ) error { -// return w.Wallet.IssueAtomicTx( -// tx, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueAtomicTx( + tx *evm.Tx, + options ...common.Option, +) error { + return w.Wallet.IssueAtomicTx( + tx, + common.UnionOptions(w.options, options)..., + ) +} diff --git a/wallet/subnet/primary/api.go b/wallet/subnet/primary/api.go index 3260c05a0a1b..3ac72c217884 100644 --- a/wallet/subnet/primary/api.go +++ b/wallet/subnet/primary/api.go @@ -5,6 +5,12 @@ package primary import ( "context" + "fmt" + + "github.com/ava-labs/coreth/ethclient" + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ethereum/go-ethereum/common" "github.com/ava-labs/avalanchego/api/info" "github.com/ava-labs/avalanchego/codec" @@ -16,6 +22,7 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm" "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" ) @@ -52,9 +59,9 @@ type AVAXState struct { PCTX p.Context XClient avm.Client XCTX x.Context - // CClient evm.Client - // CCTX c.Context - UTXOs UTXOs + CClient evm.Client + CCTX c.Context + UTXOs UTXOs } func FetchState( @@ -68,7 +75,7 @@ func FetchState( infoClient := info.NewClient(uri) pClient := platformvm.NewClient(uri) xClient := avm.NewClient(uri, "X") - // cClient := evm.NewCChainClient(uri) + cClient := evm.NewCChainClient(uri) pCTX, err := p.NewContextFromClients(ctx, infoClient, xClient) if err != nil { @@ -80,10 +87,10 @@ func FetchState( return nil, err } - // cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) - // if err != nil { - // return nil, err - // } + cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) + if err != nil { + return nil, err + } utxos := NewUTXOs() addrList := addrs.List() @@ -102,11 +109,11 @@ func FetchState( client: xClient, codec: x.Parser.Codec(), }, - // { - // id: cCTX.BlockchainID(), - // client: cClient, - // codec: evm.Codec, - // }, + { + id: cCTX.BlockchainID(), + client: cClient, + codec: evm.Codec, + }, } for _, destinationChain := range chains { for _, sourceChain := range chains { @@ -129,52 +136,52 @@ func FetchState( PCTX: pCTX, XClient: xClient, XCTX: xCTX, - // CClient: cClient, - // CCTX: cCTX, - UTXOs: utxos, + CClient: cClient, + CCTX: cCTX, + UTXOs: utxos, }, nil } -// type EthState struct { -// Client ethclient.Client -// Accounts map[common.Address]*c.Account -// } - -// func FetchEthState( -// ctx context.Context, -// uri string, -// addrs set.Set[common.Address], -// ) (*EthState, error) { -// path := fmt.Sprintf( -// "%s/ext/%s/C/rpc", -// uri, -// constants.ChainAliasPrefix, -// ) -// client, err := ethclient.Dial(path) -// if err != nil { -// return nil, err -// } - -// accounts := make(map[common.Address]*c.Account, addrs.Len()) -// for addr := range addrs { -// balance, err := client.BalanceAt(ctx, addr, nil) -// if err != nil { -// return nil, err -// } -// nonce, err := client.NonceAt(ctx, addr, nil) -// if err != nil { -// return nil, err -// } -// accounts[addr] = &c.Account{ -// Balance: balance, -// Nonce: nonce, -// } -// } -// return &EthState{ -// Client: client, -// Accounts: accounts, -// }, nil -// } +type EthState struct { + Client ethclient.Client + Accounts map[common.Address]*c.Account +} + +func FetchEthState( + ctx context.Context, + uri string, + addrs set.Set[common.Address], +) (*EthState, error) { + path := fmt.Sprintf( + "%s/ext/%s/C/rpc", + uri, + constants.ChainAliasPrefix, + ) + client, err := ethclient.Dial(path) + if err != nil { + return nil, err + } + + accounts := make(map[common.Address]*c.Account, addrs.Len()) + for addr := range addrs { + balance, err := client.BalanceAt(ctx, addr, nil) + if err != nil { + return nil, err + } + nonce, err := client.NonceAt(ctx, addr, nil) + if err != nil { + return nil, err + } + accounts[addr] = &c.Account{ + Balance: balance, + Nonce: nonce, + } + } + return &EthState{ + Client: client, + Accounts: accounts, + }, nil +} // AddAllUTXOs fetches all the UTXOs referenced by [addresses] that were sent // from [sourceChainID] to [destinationChainID] from the [client]. It then uses diff --git a/wallet/subnet/primary/example_test.go b/wallet/subnet/primary/example_test.go index 4a73e8c070b2..483c049d4ac0 100644 --- a/wallet/subnet/primary/example_test.go +++ b/wallet/subnet/primary/example_test.go @@ -30,7 +30,7 @@ func ExampleWallet() { wallet, err := MakeWallet(ctx, &WalletConfig{ URI: LocalAPIURI, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet with: %s\n", err) diff --git a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go index 21c081d2982b..d5e8ce422307 100644 --- a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go @@ -46,9 +46,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/add-primary-validator/main.go b/wallet/subnet/primary/examples/add-primary-validator/main.go index 13c28f995f63..a56dae23db3a 100644 --- a/wallet/subnet/primary/examples/add-primary-validator/main.go +++ b/wallet/subnet/primary/examples/add-primary-validator/main.go @@ -45,7 +45,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/c-chain-export/main.go b/wallet/subnet/primary/examples/c-chain-export/main.go index a6b9a0c810b8..fec55c899feb 100644 --- a/wallet/subnet/primary/examples/c-chain-export/main.go +++ b/wallet/subnet/primary/examples/c-chain-export/main.go @@ -3,70 +3,70 @@ package main -// import ( -// "context" -// "log" -// "time" +import ( + "context" + "log" + "time" -// "github.com/ava-labs/avalanchego/genesis" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary" -// ) + "github.com/ava-labs/avalanchego/genesis" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary" +) -// func main() { -// key := genesis.EWOQKey -// uri := primary.LocalAPIURI -// kc := secp256k1fx.NewKeychain(key) -// avaxAddr := key.Address() +func main() { + key := genesis.EWOQKey + uri := primary.LocalAPIURI + kc := secp256k1fx.NewKeychain(key) + avaxAddr := key.Address() -// ctx := context.Background() + ctx := context.Background() -// // MakeWallet fetches the available UTXOs owned by [kc] on the network that -// // [uri] is hosting. -// walletSyncStartTime := time.Now() -// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ -// URI: uri, -// AVAXKeychain: kc, -// EthKeychain: kc, -// }) -// if err != nil { -// log.Fatalf("failed to initialize wallet: %s\n", err) -// } -// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) + // MakeWallet fetches the available UTXOs owned by [kc] on the network that + // [uri] is hosting. + walletSyncStartTime := time.Now() + wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, + }) + if err != nil { + log.Fatalf("failed to initialize wallet: %s\n", err) + } + log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) -// // Get the P-chain wallet -// pWallet := wallet.P() -// cWallet := wallet.C() + // Get the P-chain wallet + pWallet := wallet.P() + cWallet := wallet.C() -// // Pull out useful constants to use when issuing transactions. -// cChainID := cWallet.BlockchainID() -// owner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// avaxAddr, -// }, -// } + // Pull out useful constants to use when issuing transactions. + cChainID := cWallet.BlockchainID() + owner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + avaxAddr, + }, + } -// exportStartTime := time.Now() -// exportTx, err := cWallet.IssueExportTx( -// constants.PlatformChainID, -// []*secp256k1fx.TransferOutput{{ -// Amt: units.Avax, -// OutputOwners: owner, -// }}, -// ) -// if err != nil { -// log.Fatalf("failed to issue export transaction: %s\n", err) -// } -// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) + exportStartTime := time.Now() + exportTx, err := cWallet.IssueExportTx( + constants.PlatformChainID, + []*secp256k1fx.TransferOutput{{ + Amt: units.Avax, + OutputOwners: owner, + }}, + ) + if err != nil { + log.Fatalf("failed to issue export transaction: %s\n", err) + } + log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) -// importStartTime := time.Now() -// importTx, err := pWallet.IssueImportTx(cChainID, &owner) -// if err != nil { -// log.Fatalf("failed to issue import transaction: %s\n", err) -// } -// log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) -// } + importStartTime := time.Now() + importTx, err := pWallet.IssueImportTx(cChainID, &owner) + if err != nil { + log.Fatalf("failed to issue import transaction: %s\n", err) + } + log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) +} diff --git a/wallet/subnet/primary/examples/c-chain-import/main.go b/wallet/subnet/primary/examples/c-chain-import/main.go index 2d9b8a244cb0..b4dc4e603eb3 100644 --- a/wallet/subnet/primary/examples/c-chain-import/main.go +++ b/wallet/subnet/primary/examples/c-chain-import/main.go @@ -3,75 +3,75 @@ package main -// import ( -// "context" -// "log" -// "time" +import ( + "context" + "log" + "time" -// "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/coreth/plugin/evm" -// "github.com/ava-labs/avalanchego/genesis" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary" -// ) + "github.com/ava-labs/avalanchego/genesis" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary" +) -// func main() { -// key := genesis.EWOQKey -// uri := primary.LocalAPIURI -// kc := secp256k1fx.NewKeychain(key) -// avaxAddr := key.Address() -// ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) +func main() { + key := genesis.EWOQKey + uri := primary.LocalAPIURI + kc := secp256k1fx.NewKeychain(key) + avaxAddr := key.Address() + ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) -// ctx := context.Background() + ctx := context.Background() -// // MakeWallet fetches the available UTXOs owned by [kc] on the network that -// // [uri] is hosting. -// walletSyncStartTime := time.Now() -// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ -// URI: uri, -// AVAXKeychain: kc, -// EthKeychain: kc, -// }) -// if err != nil { -// log.Fatalf("failed to initialize wallet: %s\n", err) -// } -// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) + // MakeWallet fetches the available UTXOs owned by [kc] on the network that + // [uri] is hosting. + walletSyncStartTime := time.Now() + wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, + }) + if err != nil { + log.Fatalf("failed to initialize wallet: %s\n", err) + } + log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) -// // Get the P-chain wallet -// pWallet := wallet.P() -// cWallet := wallet.C() + // Get the P-chain wallet + pWallet := wallet.P() + cWallet := wallet.C() -// // Pull out useful constants to use when issuing transactions. -// cChainID := cWallet.BlockchainID() -// avaxAssetID := cWallet.AVAXAssetID() -// owner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// avaxAddr, -// }, -// } + // Pull out useful constants to use when issuing transactions. + cChainID := cWallet.BlockchainID() + avaxAssetID := cWallet.AVAXAssetID() + owner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + avaxAddr, + }, + } -// exportStartTime := time.Now() -// exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ -// Asset: avax.Asset{ID: avaxAssetID}, -// Out: &secp256k1fx.TransferOutput{ -// Amt: units.Avax, -// OutputOwners: owner, -// }, -// }}) -// if err != nil { -// log.Fatalf("failed to issue export transaction: %s\n", err) -// } -// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) + exportStartTime := time.Now() + exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ + Asset: avax.Asset{ID: avaxAssetID}, + Out: &secp256k1fx.TransferOutput{ + Amt: units.Avax, + OutputOwners: owner, + }, + }}) + if err != nil { + log.Fatalf("failed to issue export transaction: %s\n", err) + } + log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) -// importStartTime := time.Now() -// importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) -// if err != nil { -// log.Fatalf("failed to issue import transaction: %s\n", err) -// } -// log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) -// } + importStartTime := time.Now() + importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) + if err != nil { + log.Fatalf("failed to issue import transaction: %s\n", err) + } + log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) +} diff --git a/wallet/subnet/primary/examples/create-asset/main.go b/wallet/subnet/primary/examples/create-asset/main.go index 0bccfbb5fc52..30804f083df6 100644 --- a/wallet/subnet/primary/examples/create-asset/main.go +++ b/wallet/subnet/primary/examples/create-asset/main.go @@ -30,7 +30,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-chain/main.go b/wallet/subnet/primary/examples/create-chain/main.go index 521a3cca53cf..5e6898a1b649 100644 --- a/wallet/subnet/primary/examples/create-chain/main.go +++ b/wallet/subnet/primary/examples/create-chain/main.go @@ -41,9 +41,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/create-locked-stakeable/main.go b/wallet/subnet/primary/examples/create-locked-stakeable/main.go index 92f1b5cb0e1b..e688968e9e8a 100644 --- a/wallet/subnet/primary/examples/create-locked-stakeable/main.go +++ b/wallet/subnet/primary/examples/create-locked-stakeable/main.go @@ -39,7 +39,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-subnet/main.go b/wallet/subnet/primary/examples/create-subnet/main.go index 3e8d69bc016a..add98ea7931c 100644 --- a/wallet/subnet/primary/examples/create-subnet/main.go +++ b/wallet/subnet/primary/examples/create-subnet/main.go @@ -28,7 +28,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/remove-subnet-validator/main.go b/wallet/subnet/primary/examples/remove-subnet-validator/main.go index 46f4b85124db..2842c7c0a790 100644 --- a/wallet/subnet/primary/examples/remove-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/remove-subnet-validator/main.go @@ -38,9 +38,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/wallet.go b/wallet/subnet/primary/wallet.go index de50d12f866b..54de390d029c 100644 --- a/wallet/subnet/primary/wallet.go +++ b/wallet/subnet/primary/wallet.go @@ -11,6 +11,7 @@ import ( "github.com/ava-labs/avalanchego/utils/crypto/keychain" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" @@ -22,13 +23,13 @@ var _ Wallet = (*wallet)(nil) type Wallet interface { P() p.Wallet X() x.Wallet - // C() c.Wallet + C() c.Wallet } type wallet struct { p p.Wallet x x.Wallet - // c c.Wallet + c c.Wallet } func (w *wallet) P() p.Wallet { @@ -39,16 +40,16 @@ func (w *wallet) X() x.Wallet { return w.x } -// func (w *wallet) C() c.Wallet { -// return w.c -// } +func (w *wallet) C() c.Wallet { + return w.c +} // Creates a new default wallet -func NewWallet(p p.Wallet, x x.Wallet /*, c c.Wallet*/) Wallet { +func NewWallet(p p.Wallet, x x.Wallet, c c.Wallet) Wallet { return &wallet{ p: p, x: x, - // c: c, + c: c, } } @@ -57,7 +58,7 @@ func NewWalletWithOptions(w Wallet, options ...common.Option) Wallet { return NewWallet( p.NewWalletWithOptions(w.P(), options...), x.NewWalletWithOptions(w.X(), options...), - // c.NewWalletWithOptions(w.C(), options...), + c.NewWalletWithOptions(w.C(), options...), ) } @@ -66,7 +67,7 @@ type WalletConfig struct { URI string // required // Keys to use for signing all transactions. AVAXKeychain keychain.Keychain // required - // EthKeychain c.EthKeychain // required + EthKeychain c.EthKeychain // required // Set of P-chain transactions that the wallet should know about to be able // to generate transactions. PChainTxs map[ids.ID]*txs.Tx // optional @@ -92,11 +93,11 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { return nil, err } - // ethAddrs := config.EthKeychain.EthAddresses() - // ethState, err := FetchEthState(ctx, config.URI, ethAddrs) - // if err != nil { - // return nil, err - // } + ethAddrs := config.EthKeychain.EthAddresses() + ethState, err := FetchEthState(ctx, config.URI, ethAddrs) + if err != nil { + return nil, err + } pChainTxs := config.PChainTxs if pChainTxs == nil { @@ -126,15 +127,15 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { xBuilder := x.NewBuilder(avaxAddrs, xBackend) xSigner := x.NewSigner(config.AVAXKeychain, xBackend) - // cChainID := avaxState.CCTX.BlockchainID() - // cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) - // cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) - // cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) - // cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) + cChainID := avaxState.CCTX.BlockchainID() + cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) + cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) + cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) + cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) return NewWallet( p.NewWallet(pBuilder, pSigner, avaxState.PClient, pBackend), x.NewWallet(xBuilder, xSigner, avaxState.XClient, xBackend), - // c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), + c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), ), nil } From d89f1e13de3659d16425bbfea91ae40b9702f860 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Mon, 30 Oct 2023 23:31:46 +0100 Subject: [PATCH 22/36] bumped coreth version --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3da9d583a5ae..36169c02ada2 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/DataDog/zstd v1.5.2 github.com/Microsoft/go-winio v0.5.2 github.com/NYTimes/gziphandler v1.1.1 - github.com/ava-labs/coreth v0.12.8-0.20231030220806-c0a1f8d34b62 + github.com/ava-labs/coreth v0.12.8-0.20231030222927-3e0bae2973cf github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 github.com/btcsuite/btcd/btcutil v1.1.3 github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 diff --git a/go.sum b/go.sum index 36e8114e65d9..6b6489691dea 100644 --- a/go.sum +++ b/go.sum @@ -62,8 +62,8 @@ github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/ava-labs/coreth v0.12.8-0.20231030220806-c0a1f8d34b62 h1:SwAADPPOj2aOZX3rqkKDW/P5g9aKxbVG9tWuy4Md20E= -github.com/ava-labs/coreth v0.12.8-0.20231030220806-c0a1f8d34b62/go.mod h1:ifFsmfVHQrMi4jXcnFXch5N1J2tb/nIx8W5sek7dg7U= +github.com/ava-labs/coreth v0.12.8-0.20231030222927-3e0bae2973cf h1:6PdxHf5rJwwg7h9ZVOBK1z9mAgg/ZQRl9C1SDpc7c14= +github.com/ava-labs/coreth v0.12.8-0.20231030222927-3e0bae2973cf/go.mod h1:ifFsmfVHQrMi4jXcnFXch5N1J2tb/nIx8W5sek7dg7U= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 h1:EdxD90j5sClfL5Ngpz2TlnbnkNYdFPDXa0jDOjam65c= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7/go.mod h1:XhiXSrh90sHUbkERzaxEftCmUz53eCijshDLZ4fByVM= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= From 8a7867a612be548ea7c2e6c868520a1b5c9ac1f4 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Tue, 31 Oct 2023 00:07:25 +0100 Subject: [PATCH 23/36] moved up proposerVM block backfilling --- vms/proposervm/state_syncable_vm.go | 25 ++++--------------------- vms/proposervm/vm.go | 4 ---- 2 files changed, 4 insertions(+), 25 deletions(-) diff --git a/vms/proposervm/state_syncable_vm.go b/vms/proposervm/state_syncable_vm.go index 270b0f7b5788..32e78444b6c7 100644 --- a/vms/proposervm/state_syncable_vm.go +++ b/vms/proposervm/state_syncable_vm.go @@ -161,27 +161,10 @@ func (vm *VM) buildStateSummary(ctx context.Context, innerSummary block.StateSum }, nil } -func (vm *VM) BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) { - if vm.ssVM == nil { - return ids.Empty, nil - } - - return vm.ssVM.BackfillBlocksEnabled(ctx) +func (*VM) BackfillBlocksEnabled(context.Context) (ids.ID, error) { + return ids.Empty, block.ErrBlockBackfillingNotEnabled } -func (vm *VM) BackfillBlocks(ctx context.Context, blksBytes [][]byte) (ids.ID, error) { - innerBlksBytes := make([][]byte, 0, len(blksBytes)) - for i, blkBytes := range blksBytes { - blk, err := vm.parseProposerBlock(ctx, blkBytes) - if err != nil { - return ids.Empty, fmt.Errorf("failed parsing backfilled block, index %d, %w", i, err) - } - // TODO: consider validating that block is at least below last accepted block - // or that block has not been stored yet - if err := blk.acceptOuterBlk(); err != nil { - return ids.Empty, fmt.Errorf("failed indexing backfilled block, index %d, %w", i, err) - } - innerBlksBytes = append(innerBlksBytes, blk.getInnerBlk().Bytes()) - } - return vm.ssVM.BackfillBlocks(ctx, innerBlksBytes) +func (*VM) BackfillBlocks(context.Context, [][]byte) (ids.ID, error) { + return ids.Empty, block.ErrStopBlockBackfilling } diff --git a/vms/proposervm/vm.go b/vms/proposervm/vm.go index 1bfdf13da0a5..a101be86f574 100644 --- a/vms/proposervm/vm.go +++ b/vms/proposervm/vm.go @@ -327,10 +327,6 @@ func (vm *VM) BuildBlock(ctx context.Context) (snowman.Block, error) { } func (vm *VM) ParseBlock(ctx context.Context, b []byte) (snowman.Block, error) { - return vm.parseProposerBlock(ctx, b) -} - -func (vm *VM) parseProposerBlock(ctx context.Context, b []byte) (Block, error) { if blk, err := vm.parsePostForkBlock(ctx, b); err == nil { return blk, nil } From ae98edef8dfc0605a62375bc2db0fb269d544abc Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 1 Nov 2023 10:04:18 +0100 Subject: [PATCH 24/36] changing block backfilling interface --- proto/pb/vm/vm.pb.go | 49 ++++++++++----- proto/vm/vm.proto | 6 +- .../snowman/block/mocks/state_syncable_vm.go | 14 +++-- .../engine/snowman/block/state_syncable_vm.go | 10 ++-- .../snowman/block/test_state_syncable_vm.go | 12 ++-- .../snowman/syncer/blocks_backfiller.go | 4 +- .../transitive_block_backfilling_test.go | 60 +++++++++++-------- vms/metervm/state_syncable_vm.go | 20 +++---- vms/proposervm/state_syncable_vm.go | 8 +-- vms/rpcchainvm/vm_client.go | 16 ++--- vms/rpcchainvm/vm_server.go | 24 ++++---- vms/tracedvm/state_syncable_vm.go | 8 +-- 12 files changed, 134 insertions(+), 97 deletions(-) diff --git a/proto/pb/vm/vm.pb.go b/proto/pb/vm/vm.pb.go index 187b8e34b816..8180263a90eb 100644 --- a/proto/pb/vm/vm.pb.go +++ b/proto/pb/vm/vm.pb.go @@ -2940,8 +2940,9 @@ type BackfillBlocksEnabledResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Err Error `protobuf:"varint,2,opt,name=err,proto3,enum=vm.Error" json:"err,omitempty"` + Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Height uint64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` + Err Error `protobuf:"varint,3,opt,name=err,proto3,enum=vm.Error" json:"err,omitempty"` } func (x *BackfillBlocksEnabledResponse) Reset() { @@ -2983,6 +2984,13 @@ func (x *BackfillBlocksEnabledResponse) GetId() []byte { return nil } +func (x *BackfillBlocksEnabledResponse) GetHeight() uint64 { + if x != nil { + return x.Height + } + return 0 +} + func (x *BackfillBlocksEnabledResponse) GetErr() Error { if x != nil { return x.Err @@ -3042,8 +3050,9 @@ type BackfillBlocksResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Err Error `protobuf:"varint,2,opt,name=err,proto3,enum=vm.Error" json:"err,omitempty"` + Id []byte `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Height uint64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` + Err Error `protobuf:"varint,3,opt,name=err,proto3,enum=vm.Error" json:"err,omitempty"` } func (x *BackfillBlocksResponse) Reset() { @@ -3085,6 +3094,13 @@ func (x *BackfillBlocksResponse) GetId() []byte { return nil } +func (x *BackfillBlocksResponse) GetHeight() uint64 { + if x != nil { + return x.Height + } + return 0 +} + func (x *BackfillBlocksResponse) GetErr() Error { if x != nil { return x.Err @@ -3499,19 +3515,22 @@ var file_vm_vm_proto_rawDesc = []byte{ 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, - 0x6d, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0x4c, 0x0a, 0x1d, + 0x6d, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0x64, 0x0a, 0x1d, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 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, 0x1b, 0x0a, - 0x03, 0x65, 0x72, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, 0x6d, 0x2e, - 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0x36, 0x0a, 0x15, 0x42, 0x61, - 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6b, 0x73, 0x5f, 0x62, 0x79, 0x74, 0x65, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x62, 0x6c, 0x6b, 0x73, 0x42, 0x79, 0x74, - 0x65, 0x73, 0x22, 0x45, 0x0a, 0x16, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x73, 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, 0x1b, 0x0a, 0x03, - 0x65, 0x72, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, 0x6d, 0x2e, 0x45, + 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, 0x04, 0x52, 0x06, 0x68, + 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1b, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, 0x6d, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x03, 0x65, + 0x72, 0x72, 0x22, 0x36, 0x0a, 0x15, 0x42, 0x61, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x62, + 0x6c, 0x6b, 0x73, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, + 0x09, 0x62, 0x6c, 0x6b, 0x73, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x5d, 0x0a, 0x16, 0x42, 0x61, + 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 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, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1b, 0x0a, 0x03, + 0x65, 0x72, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x76, 0x6d, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x03, 0x65, 0x72, 0x72, 0x22, 0x31, 0x0a, 0x19, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, diff --git a/proto/vm/vm.proto b/proto/vm/vm.proto index fb795777e7e7..e5da65f77e37 100644 --- a/proto/vm/vm.proto +++ b/proto/vm/vm.proto @@ -402,7 +402,8 @@ message GetStateSummaryResponse { message BackfillBlocksEnabledResponse { bytes id = 1; - Error err = 2; + uint64 height = 2; + Error err = 3; } message BackfillBlocksRequest { @@ -411,7 +412,8 @@ message BackfillBlocksRequest { message BackfillBlocksResponse { bytes id = 1; - Error err = 2; + uint64 height = 2; + Error err = 3; } message StateSummaryAcceptRequest { diff --git a/snow/engine/snowman/block/mocks/state_syncable_vm.go b/snow/engine/snowman/block/mocks/state_syncable_vm.go index 64470a599656..90f929f4f762 100644 --- a/snow/engine/snowman/block/mocks/state_syncable_vm.go +++ b/snow/engine/snowman/block/mocks/state_syncable_vm.go @@ -40,12 +40,13 @@ func (m *MockStateSyncableVM) EXPECT() *MockStateSyncableVMMockRecorder { } // BackfillBlocks mocks base method. -func (m *MockStateSyncableVM) BackfillBlocks(arg0 context.Context, arg1 [][]byte) (ids.ID, error) { +func (m *MockStateSyncableVM) BackfillBlocks(arg0 context.Context, arg1 [][]byte) (ids.ID, uint64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "BackfillBlocks", arg0, arg1) ret0, _ := ret[0].(ids.ID) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret1, _ := ret[1].(uint64) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 } // BackfillBlocks indicates an expected call of BackfillBlocks. @@ -55,12 +56,13 @@ func (mr *MockStateSyncableVMMockRecorder) BackfillBlocks(arg0, arg1 interface{} } // BackfillBlocksEnabled mocks base method. -func (m *MockStateSyncableVM) BackfillBlocksEnabled(arg0 context.Context) (ids.ID, error) { +func (m *MockStateSyncableVM) BackfillBlocksEnabled(arg0 context.Context) (ids.ID, uint64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "BackfillBlocksEnabled", arg0) ret0, _ := ret[0].(ids.ID) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret1, _ := ret[1].(uint64) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 } // BackfillBlocksEnabled indicates an expected call of BackfillBlocksEnabled. diff --git a/snow/engine/snowman/block/state_syncable_vm.go b/snow/engine/snowman/block/state_syncable_vm.go index 7b570bb979aa..811d6f3b19d2 100644 --- a/snow/engine/snowman/block/state_syncable_vm.go +++ b/snow/engine/snowman/block/state_syncable_vm.go @@ -52,15 +52,17 @@ type StateSyncableVM interface { // BackfillBlocksEnabled checks if VM wants to download all blocks from state summary one // down to genesis. // + // Returns the ID and height of the block it wants to start backfilling from. // Returns ErrBlockBackfillingNotEnabled if block backfilling is not enabled. - BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) + // BackfillBlocksEnabled can be called multiple times by the engine + BackfillBlocksEnabled(ctx context.Context) (ids.ID, uint64, error) // BackfillBlocks passes blocks bytes retrieved via GetAncestors calls to the VM // It's left to the VM the to parse, validate and index the blocks. // BackfillBlocks returns the next block ID to be requested and an error - // If BackfillBlocks returns no error, engine will request the blockID returned by the VM - // If BackfillBlocks returns ErrStopBlockBackfilling, engine will stop requesting block ancestors + // Returns the ID and height of the block it wants to start backfilling from. + // Returns [ErrStopBlockBackfilling] if VM has done backfilling; engine will stop requesting blocks. // If BackfillBlocks returns any other error, engine will issue a GetAncestor call to a different peer // with the previously requested block ID - BackfillBlocks(ctx context.Context, blocks [][]byte) (ids.ID, error) + BackfillBlocks(ctx context.Context, blocks [][]byte) (ids.ID, uint64, error) } diff --git a/snow/engine/snowman/block/test_state_syncable_vm.go b/snow/engine/snowman/block/test_state_syncable_vm.go index 913989c7853e..5199685bafe1 100644 --- a/snow/engine/snowman/block/test_state_syncable_vm.go +++ b/snow/engine/snowman/block/test_state_syncable_vm.go @@ -40,8 +40,8 @@ type TestStateSyncableVM struct { ParseStateSummaryF func(ctx context.Context, summaryBytes []byte) (StateSummary, error) GetStateSummaryF func(ctx context.Context, summaryHeight uint64) (StateSummary, error) - BackfillBlocksEnabledF func(context.Context) (ids.ID, error) - BackfillBlocksF func(context.Context, [][]byte) (ids.ID, error) + BackfillBlocksEnabledF func(context.Context) (ids.ID, uint64, error) + BackfillBlocksF func(context.Context, [][]byte) (ids.ID, uint64, error) } func (vm *TestStateSyncableVM) StateSyncEnabled(ctx context.Context) (bool, error) { @@ -94,22 +94,22 @@ func (vm *TestStateSyncableVM) GetStateSummary(ctx context.Context, summaryHeigh return nil, errGetStateSummary } -func (vm *TestStateSyncableVM) BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) { +func (vm *TestStateSyncableVM) BackfillBlocksEnabled(ctx context.Context) (ids.ID, uint64, error) { if vm.BackfillBlocksEnabledF != nil { return vm.BackfillBlocksEnabledF(ctx) } if vm.CantGetStateSummary && vm.T != nil { require.FailNow(vm.T, errGetStateSummary.Error()) } - return ids.Empty, errBackfillBlocksEnabled + return ids.Empty, 0, errBackfillBlocksEnabled } -func (vm *TestStateSyncableVM) BackfillBlocks(ctx context.Context, blocks [][]byte) (ids.ID, error) { +func (vm *TestStateSyncableVM) BackfillBlocks(ctx context.Context, blocks [][]byte) (ids.ID, uint64, error) { if vm.BackfillBlocksF != nil { return vm.BackfillBlocksF(ctx, blocks) } if vm.CantGetStateSummary && vm.T != nil { require.FailNow(vm.T, errGetStateSummary.Error()) } - return ids.Empty, errBackfillBlock + return ids.Empty, 0, errBackfillBlock } diff --git a/snow/engine/snowman/syncer/blocks_backfiller.go b/snow/engine/snowman/syncer/blocks_backfiller.go index 60a0150063a7..94964644250d 100644 --- a/snow/engine/snowman/syncer/blocks_backfiller.go +++ b/snow/engine/snowman/syncer/blocks_backfiller.go @@ -64,7 +64,7 @@ func (bb *BlockBackfiller) Start(ctx context.Context) error { return nil // nothing to do } - switch wantedBlk, err := ssVM.BackfillBlocksEnabled(ctx); { + switch wantedBlk, _, err := ssVM.BackfillBlocksEnabled(ctx); { case err == block.ErrBlockBackfillingNotEnabled: bb.Ctx.Log.Info("block backfilling not enabled") bb.Ctx.StateSyncing.Set(false) @@ -119,7 +119,7 @@ func (bb *BlockBackfiller) Ancestors(ctx context.Context, nodeID ids.NodeID, req return nil // nothing to do } - switch nextWantedBlkID, err := ssVM.BackfillBlocks(ctx, blks); { + switch nextWantedBlkID, _, err := ssVM.BackfillBlocks(ctx, blks); { case err == block.ErrStopBlockBackfilling: bb.Ctx.Log.Info("block backfilling done") bb.Ctx.StateSyncing.Set(false) diff --git a/snow/engine/snowman/transitive_block_backfilling_test.go b/snow/engine/snowman/transitive_block_backfilling_test.go index 08d69f2ddbde..bb74ea3b4181 100644 --- a/snow/engine/snowman/transitive_block_backfilling_test.go +++ b/snow/engine/snowman/transitive_block_backfilling_test.go @@ -33,8 +33,9 @@ func TestGetAncestorsRequestIssuedIfBlockBackfillingIsEnabled(t *testing.T) { // enable block backfilling and check blocks request starts with block provided by VM reqBlk := ids.GenerateTestID() - vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, error) { - return reqBlk, nil + dummyHeight := uint64(1492) + vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, uint64, error) { + return reqBlk, dummyHeight, nil } var issuedBlkID ids.ID @@ -59,8 +60,9 @@ func TestGetAncestorsRequestNotIssuedIfBlockBackfillingIsNotEnabled(t *testing.T require.NoError(err) // disable block backfilling - vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, error) { - return ids.Empty, block.ErrBlockBackfillingNotEnabled + dummyHeight := uint64(1492) + vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, uint64, error) { + return ids.Empty, dummyHeight, block.ErrBlockBackfillingNotEnabled } // this will make engine Start fail if SendGetAncestor is attempted @@ -83,8 +85,9 @@ func TestEngineErrsIfBlockBackfillingIsEnabledCheckErrs(t *testing.T) { // let BackfillBlocksEnabled err with non-flag error customErr := errors.New("a custom error") - vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, error) { - return ids.Empty, customErr + dummyHeight := uint64(1492) + vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, uint64, error) { + return ids.Empty, dummyHeight, customErr } dummyCtx := context.Background() @@ -105,8 +108,9 @@ func TestEngineErrsIfThereAreNoPeersToDownloadBlocksFrom(t *testing.T) { // enable block backfilling reqBlk := ids.GenerateTestID() - vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, error) { - return reqBlk, nil + dummyHeight := uint64(1492) + vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, uint64, error) { + return reqBlk, dummyHeight, nil } var ( @@ -154,8 +158,9 @@ func TestAncestorsProcessing(t *testing.T) { // enable block backfilling reqBlkFirst := ids.GenerateTestID() - vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, error) { - return reqBlkFirst, nil + dummyHeight := uint64(1492) + vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, uint64, error) { + return reqBlkFirst, dummyHeight, nil } issuedBlk := ids.Empty sender.SendGetAncestorsF = func(ctx context.Context, ni ids.NodeID, u uint32, blkID ids.ID) { @@ -174,9 +179,10 @@ func TestAncestorsProcessing(t *testing.T) { pushedBlks [][]byte reqBlkSecond = ids.GenerateTestID() ) - vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, error) { + + vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, uint64, error) { pushedBlks = b - return reqBlkSecond, nil + return reqBlkSecond, dummyHeight, nil } { @@ -227,8 +233,9 @@ func TestGetAncestorsFailedProcessing(t *testing.T) { // enable block backfilling reqBlkFirst := ids.GenerateTestID() - vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, error) { - return reqBlkFirst, nil + dummyHeight := uint64(1492) + vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, uint64, error) { + return reqBlkFirst, dummyHeight, nil } issuedBlk := ids.Empty sender.SendGetAncestorsF = func(ctx context.Context, ni ids.NodeID, u uint32, blkID ids.ID) { @@ -247,9 +254,9 @@ func TestGetAncestorsFailedProcessing(t *testing.T) { pushedBlks [][]byte reqBlkSecond = ids.GenerateTestID() ) - vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, error) { + vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, uint64, error) { pushedBlks = b - return reqBlkSecond, nil + return reqBlkSecond, dummyHeight, nil } { // handle Ancestor response from unexpected nodeID @@ -289,8 +296,9 @@ func TestBackfillingTerminatedByVM(t *testing.T) { // enable block backfilling reqBlkFirst := ids.GenerateTestID() - vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, error) { - return reqBlkFirst, nil + dummyHeight := uint64(1492) + vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, uint64, error) { + return reqBlkFirst, dummyHeight, nil } // start the engine @@ -310,9 +318,9 @@ func TestBackfillingTerminatedByVM(t *testing.T) { // 1. Successfully request and download some blocks { responseReqID++ - vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, error) { + vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, uint64, error) { pushedBlks = true - return nextRequestedBlk, nil // requestedBlkID does not really matter here + return nextRequestedBlk, dummyHeight, nil // requestedBlkID does not really matter here } sender.SendGetAncestorsF = func(ctx context.Context, ni ids.NodeID, u uint32, blkID ids.ID) { issuedBlk = blkID @@ -329,9 +337,9 @@ func TestBackfillingTerminatedByVM(t *testing.T) { issuedBlk = ids.Empty responseReqID++ - vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, error) { + vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, uint64, error) { pushedBlks = true - return nextRequestedBlk, nil // requestedBlkID does not really matter here + return nextRequestedBlk, dummyHeight, nil // requestedBlkID does not really matter here } sender.SendGetAncestorsF = func(ctx context.Context, ni ids.NodeID, u uint32, blkID ids.ID) { issuedBlk = blkID @@ -348,9 +356,9 @@ func TestBackfillingTerminatedByVM(t *testing.T) { issuedBlk = ids.Empty responseReqID++ - vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, error) { + vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, uint64, error) { pushedBlks = true - return ids.Empty, errors.New("custom error upon backfilling") + return ids.Empty, dummyHeight, errors.New("custom error upon backfilling") } sender.SendGetAncestorsF = func(ctx context.Context, ni ids.NodeID, u uint32, blkID ids.ID) { issuedBlk = blkID @@ -367,9 +375,9 @@ func TestBackfillingTerminatedByVM(t *testing.T) { pushedBlks = false responseReqID++ - vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, error) { + vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, uint64, error) { pushedBlks = true - return ids.Empty, block.ErrStopBlockBackfilling + return ids.Empty, dummyHeight, block.ErrStopBlockBackfilling } sender.SendGetAncestorsF = func(ctx context.Context, ni ids.NodeID, u uint32, blkID ids.ID) { issuedBlkRequest = true diff --git a/vms/metervm/state_syncable_vm.go b/vms/metervm/state_syncable_vm.go index 092942f5b61a..f6eb4bdec4b7 100644 --- a/vms/metervm/state_syncable_vm.go +++ b/vms/metervm/state_syncable_vm.go @@ -80,36 +80,36 @@ func (vm *blockVM) GetStateSummary(ctx context.Context, height uint64) (block.St return summary, nil } -func (vm *blockVM) BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) { +func (vm *blockVM) BackfillBlocksEnabled(ctx context.Context) (ids.ID, uint64, error) { if vm.ssVM == nil { - return ids.Empty, block.ErrStateSyncableVMNotImplemented + return ids.Empty, 0, block.ErrStateSyncableVMNotImplemented } start := vm.clock.Time() - blkID, err := vm.ssVM.BackfillBlocksEnabled(ctx) + blkID, blkHeight, err := vm.ssVM.BackfillBlocksEnabled(ctx) end := vm.clock.Time() duration := float64(end.Sub(start)) if err != nil { vm.blockMetrics.backfillBlocksEnabled.Observe(duration) - return ids.Empty, err + return ids.Empty, blkHeight, err } vm.blockMetrics.backfillBlocksEnabled.Observe(duration) - return blkID, nil + return blkID, blkHeight, nil } -func (vm *blockVM) BackfillBlocks(ctx context.Context, blocks [][]byte) (ids.ID, error) { +func (vm *blockVM) BackfillBlocks(ctx context.Context, blocks [][]byte) (ids.ID, uint64, error) { if vm.ssVM == nil { - return ids.Empty, block.ErrStateSyncableVMNotImplemented + return ids.Empty, 0, block.ErrStateSyncableVMNotImplemented } start := vm.clock.Time() - nextWantedBlkID, err := vm.ssVM.BackfillBlocks(ctx, blocks) + nextWantedBlkID, nextWantedBlkHeight, err := vm.ssVM.BackfillBlocks(ctx, blocks) end := vm.clock.Time() duration := float64(end.Sub(start)) if err != nil { vm.blockMetrics.backfillBlocks.Observe(duration) - return nextWantedBlkID, err + return nextWantedBlkID, nextWantedBlkHeight, err } vm.blockMetrics.backfillBlocks.Observe(duration) - return nextWantedBlkID, nil + return nextWantedBlkID, nextWantedBlkHeight, nil } diff --git a/vms/proposervm/state_syncable_vm.go b/vms/proposervm/state_syncable_vm.go index 32e78444b6c7..440e5f17223d 100644 --- a/vms/proposervm/state_syncable_vm.go +++ b/vms/proposervm/state_syncable_vm.go @@ -161,10 +161,10 @@ func (vm *VM) buildStateSummary(ctx context.Context, innerSummary block.StateSum }, nil } -func (*VM) BackfillBlocksEnabled(context.Context) (ids.ID, error) { - return ids.Empty, block.ErrBlockBackfillingNotEnabled +func (*VM) BackfillBlocksEnabled(context.Context) (ids.ID, uint64, error) { + return ids.Empty, 0, block.ErrBlockBackfillingNotEnabled } -func (*VM) BackfillBlocks(context.Context, [][]byte) (ids.ID, error) { - return ids.Empty, block.ErrStopBlockBackfilling +func (*VM) BackfillBlocks(context.Context, [][]byte) (ids.ID, uint64, error) { + return ids.Empty, 0, block.ErrStopBlockBackfilling } diff --git a/vms/rpcchainvm/vm_client.go b/vms/rpcchainvm/vm_client.go index c921fe09a62b..3241c59dee89 100644 --- a/vms/rpcchainvm/vm_client.go +++ b/vms/rpcchainvm/vm_client.go @@ -815,19 +815,19 @@ func (vm *VMClient) GetStateSummary(ctx context.Context, summaryHeight uint64) ( }, err } -func (vm *VMClient) BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) { +func (vm *VMClient) BackfillBlocksEnabled(ctx context.Context) (ids.ID, uint64, error) { resp, err := vm.client.BackfillBlocksEnabled(ctx, &emptypb.Empty{}) if err != nil { - return ids.Empty, err + return ids.Empty, 0, err } err = errEnumToError[resp.Err] if err == block.ErrStateSyncableVMNotImplemented { - return ids.Empty, nil + return ids.Empty, 0, nil } - return ids.ID(resp.Id), err + return ids.ID(resp.Id), resp.Height, err } -func (vm *VMClient) BackfillBlocks(ctx context.Context, blocks [][]byte) (ids.ID, error) { +func (vm *VMClient) BackfillBlocks(ctx context.Context, blocks [][]byte) (ids.ID, uint64, error) { resp, err := vm.client.BackfillBlocks( ctx, &vmpb.BackfillBlocksRequest{ @@ -835,12 +835,12 @@ func (vm *VMClient) BackfillBlocks(ctx context.Context, blocks [][]byte) (ids.ID }, ) if err != nil { - return ids.Empty, err + return ids.Empty, 0, err } if errEnum := resp.Err; errEnum != vmpb.Error_ERROR_UNSPECIFIED { - return ids.ID(resp.Id), errEnumToError[errEnum] + return ids.ID(resp.Id), resp.Height, errEnumToError[errEnum] } - return ids.ID(resp.Id), nil + return ids.ID(resp.Id), resp.Height, nil } func (vm *VMClient) newBlockFromBuildBlock(resp *vmpb.BuildBlockResponse) (*blockClient, error) { diff --git a/vms/rpcchainvm/vm_server.go b/vms/rpcchainvm/vm_server.go index 94f9185b427f..5f43dffe8308 100644 --- a/vms/rpcchainvm/vm_server.go +++ b/vms/rpcchainvm/vm_server.go @@ -823,31 +823,35 @@ func (vm *VMServer) GetStateSummary( func (vm *VMServer) BackfillBlocksEnabled(ctx context.Context, _ *emptypb.Empty) (*vmpb.BackfillBlocksEnabledResponse, error) { var ( - blkID = ids.Empty - err error + blkID = ids.Empty + height uint64 + err error ) if vm.ssVM != nil { - blkID, err = vm.ssVM.BackfillBlocksEnabled(ctx) + blkID, height, err = vm.ssVM.BackfillBlocksEnabled(ctx) } return &vmpb.BackfillBlocksEnabledResponse{ - Id: blkID[:], - Err: errorToErrEnum[err], + Id: blkID[:], + Height: height, + Err: errorToErrEnum[err], }, errorToRPCError(err) } func (vm *VMServer) BackfillBlocks(ctx context.Context, req *vmpb.BackfillBlocksRequest) (*vmpb.BackfillBlocksResponse, error) { var ( - nextWantedBlkID ids.ID - err error + nextWantedBlkID ids.ID + nextWantedBlkHeight uint64 + err error ) if vm.ssVM != nil { - nextWantedBlkID, err = vm.ssVM.BackfillBlocks(ctx, req.BlksBytes) + nextWantedBlkID, nextWantedBlkHeight, err = vm.ssVM.BackfillBlocks(ctx, req.BlksBytes) } return &vmpb.BackfillBlocksResponse{ - Id: nextWantedBlkID[:], - Err: errorToErrEnum[err], + Id: nextWantedBlkID[:], + Height: nextWantedBlkHeight, + Err: errorToErrEnum[err], }, errorToRPCError(err) } diff --git a/vms/tracedvm/state_syncable_vm.go b/vms/tracedvm/state_syncable_vm.go index c474d3c4960b..514002056cdc 100644 --- a/vms/tracedvm/state_syncable_vm.go +++ b/vms/tracedvm/state_syncable_vm.go @@ -73,9 +73,9 @@ func (vm *blockVM) GetStateSummary(ctx context.Context, height uint64) (block.St return vm.ssVM.GetStateSummary(ctx, height) } -func (vm *blockVM) BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) { +func (vm *blockVM) BackfillBlocksEnabled(ctx context.Context) (ids.ID, uint64, error) { if vm.ssVM == nil { - return ids.Empty, block.ErrStateSyncableVMNotImplemented + return ids.Empty, 0, block.ErrStateSyncableVMNotImplemented } ctx, span := vm.tracer.Start(ctx, vm.backfillBlocksEnabledTag) @@ -84,9 +84,9 @@ func (vm *blockVM) BackfillBlocksEnabled(ctx context.Context) (ids.ID, error) { return vm.ssVM.BackfillBlocksEnabled(ctx) } -func (vm *blockVM) BackfillBlocks(ctx context.Context, blocks [][]byte) (ids.ID, error) { +func (vm *blockVM) BackfillBlocks(ctx context.Context, blocks [][]byte) (ids.ID, uint64, error) { if vm.ssVM == nil { - return ids.Empty, block.ErrStateSyncableVMNotImplemented + return ids.Empty, 0, block.ErrStateSyncableVMNotImplemented } ctx, span := vm.tracer.Start(ctx, vm.backfillBlocksTag, oteltrace.WithAttributes( From 50a01e6d778bc67e7998ae3ca5e74d0bcd360577 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 1 Nov 2023 10:19:46 +0100 Subject: [PATCH 25/36] temporarily cut coreth dependencies --- go.mod | 25 - go.sum | 76 -- node/node.go | 4 +- tests/e2e/c/dynamic_fees.go | 326 +++---- tests/e2e/c/interchain_workflow.go | 320 +++---- tests/e2e/e2e.go | 127 +-- tests/e2e/p/interchain_workflow.go | 444 +++++----- tests/e2e/x/interchain_workflow.go | 296 +++---- tests/fixture/testnet/config.go | 48 +- vms/example/xsvm/cmd/chain/create/cmd.go | 6 +- wallet/chain/c/backend.go | 300 +++---- wallet/chain/c/builder.go | 792 +++++++++--------- wallet/chain/c/builder_with_options.go | 136 +-- wallet/chain/c/context.go | 130 +-- wallet/chain/c/signer.go | 436 +++++----- wallet/chain/c/wallet.go | 402 ++++----- wallet/chain/c/wallet_with_options.go | 134 +-- wallet/subnet/primary/api.go | 119 ++- wallet/subnet/primary/example_test.go | 2 +- .../add-permissioned-subnet-validator/main.go | 6 +- .../examples/add-primary-validator/main.go | 2 +- .../primary/examples/c-chain-export/main.go | 118 +-- .../primary/examples/c-chain-import/main.go | 126 +-- .../primary/examples/create-asset/main.go | 2 +- .../primary/examples/create-chain/main.go | 6 +- .../examples/create-locked-stakeable/main.go | 2 +- .../primary/examples/create-subnet/main.go | 2 +- .../examples/remove-subnet-validator/main.go | 6 +- wallet/subnet/primary/wallet.go | 41 +- 29 files changed, 2164 insertions(+), 2270 deletions(-) diff --git a/go.mod b/go.mod index 36169c02ada2..40d59d0cb294 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,6 @@ require ( github.com/DataDog/zstd v1.5.2 github.com/Microsoft/go-winio v0.5.2 github.com/NYTimes/gziphandler v1.1.1 - github.com/ava-labs/coreth v0.12.8-0.20231030222927-3e0bae2973cf github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 github.com/btcsuite/btcd/btcutil v1.1.3 github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 @@ -72,7 +71,6 @@ require ( require ( github.com/BurntSushi/toml v1.2.1 // indirect - github.com/VictoriaMetrics/fastcache v1.10.0 // indirect github.com/benbjohnson/clock v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect @@ -81,44 +79,26 @@ require ( github.com/cockroachdb/errors v1.9.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/redact v1.1.3 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/deckarep/golang-set/v2 v2.1.0 // indirect - github.com/dlclark/regexp2 v1.7.0 // indirect - github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect - github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/frankban/quicktest v1.14.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect - github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect - github.com/go-stack/stack v1.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect - github.com/google/uuid v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 // indirect - github.com/hashicorp/go-bexpr v0.1.10 // indirect - github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/klauspost/compress v1.15.15 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/magiconair/properties v1.8.6 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/mitchellh/pointerstructure v1.2.0 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect @@ -126,17 +106,12 @@ require ( github.com/prometheus/common v0.39.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sanity-io/litter v1.5.1 // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/status-im/keycard-go v0.2.0 // indirect github.com/subosito/gotenv v1.3.0 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect - github.com/tyler-smith/go-bip39 v1.1.0 // indirect - github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa // indirect - github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/zondax/hid v0.9.1 // indirect github.com/zondax/ledger-go v0.14.1 // indirect diff --git a/go.sum b/go.sum index 6b6489691dea..09e5526b3f20 100644 --- a/go.sum +++ b/go.sum @@ -52,18 +52,12 @@ github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cq github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= -github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY= -github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/ava-labs/coreth v0.12.8-0.20231030222927-3e0bae2973cf h1:6PdxHf5rJwwg7h9ZVOBK1z9mAgg/ZQRl9C1SDpc7c14= -github.com/ava-labs/coreth v0.12.8-0.20231030222927-3e0bae2973cf/go.mod h1:ifFsmfVHQrMi4jXcnFXch5N1J2tb/nIx8W5sek7dg7U= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 h1:EdxD90j5sClfL5Ngpz2TlnbnkNYdFPDXa0jDOjam65c= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7/go.mod h1:XhiXSrh90sHUbkERzaxEftCmUz53eCijshDLZ4fByVM= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= @@ -100,18 +94,13 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -141,16 +130,12 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= -github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= @@ -161,14 +146,6 @@ github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6ps github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= -github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= -github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= -github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= -github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -185,8 +162,6 @@ github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2 github.com/ethereum/go-ethereum v1.12.0/go.mod h1:/oo2X/dZLJjf2mJ6YT9wcWxa4nNJDBKDBU6sFIpx1Gs= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -195,8 +170,6 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= @@ -220,11 +193,7 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= -github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= @@ -309,14 +278,10 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -337,17 +302,11 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 h1:kr3j8iIMR4ywO/O0rvksXaJvauGGCMg2zAZIiNZ9uIQ= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0/go.mod h1:ummNFgdgLhhX7aIiy35vVmQNS0rWXknfPE0qe6fmFXg= -github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= -github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e/go.mod h1:j9cQbcqHQujT0oKJ38PylVfqohClLr3CvDC+Qcg+lhU= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8= @@ -359,7 +318,6 @@ github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3 github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -401,7 +359,6 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -409,7 +366,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= @@ -420,17 +376,11 @@ github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -439,11 +389,8 @@ github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= -github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -462,8 +409,6 @@ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -531,8 +476,6 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sanity-io/litter v1.5.1 h1:dwnrSypP6q56o3lFxTU+t2fwQ9A+U5qrXVO4Qg9KwVU= github.com/sanity-io/litter v1.5.1/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0= @@ -568,8 +511,6 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= -github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= -github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -599,14 +540,10 @@ github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITn github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= -github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -618,8 +555,6 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1: github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= @@ -629,7 +564,6 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= @@ -727,7 +661,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -773,7 +706,6 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -797,7 +729,6 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -862,12 +793,8 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -884,7 +811,6 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -948,7 +874,6 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1073,7 +998,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= diff --git a/node/node.go b/node/node.go index 34293e85b0b6..3b3974db0401 100644 --- a/node/node.go +++ b/node/node.go @@ -25,7 +25,7 @@ import ( "go.uber.org/zap" - coreth "github.com/ava-labs/coreth/plugin/evm" + // coreth "github.com/ava-labs/coreth/plugin/evm" "github.com/ava-labs/avalanchego/api/admin" "github.com/ava-labs/avalanchego/api/auth" @@ -934,7 +934,7 @@ func (n *Node) initVMs() error { CreateAssetTxFee: n.Config.CreateAssetTxFee, }, }), - vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), + // vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), n.VMManager.RegisterFactory(context.TODO(), secp256k1fx.ID, &secp256k1fx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), nftfx.ID, &nftfx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), propertyfx.ID, &propertyfx.Factory{}), diff --git a/tests/e2e/c/dynamic_fees.go b/tests/e2e/c/dynamic_fees.go index edfbef2671a8..779c8670be37 100644 --- a/tests/e2e/c/dynamic_fees.go +++ b/tests/e2e/c/dynamic_fees.go @@ -3,166 +3,166 @@ package c -import ( - "math/big" - "strings" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/stretchr/testify/require" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/coreth/core/types" - "github.com/ava-labs/coreth/params" - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/tests" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/tests/fixture/testnet" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -) - -// This test uses the compiled bin for `hashing.sol` as -// well as its ABI contained in `hashing_contract.go`. - -var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { - require := require.New(ginkgo.GinkgoT()) - - // Need a gas limit much larger than the standard 21_000 to enable - // the contract to induce a gas price increase - const largeGasLimit = uint64(8_000_000) - - // TODO(marun) What is the significance of this value? - gasTip := big.NewInt(1000 * params.GWei) - - ginkgo.It("should ensure that the gas price is affected by load", func() { - ginkgo.By("creating a new private network to ensure isolation from other tests") - privateNetwork := e2e.Env.NewPrivateNetwork() - - ginkgo.By("allocating a pre-funded key") - key := privateNetwork.GetConfig().FundedKeys[0] - ethAddress := evm.GetEthAddress(key) - - ginkgo.By("initializing a coreth client") - node := privateNetwork.GetNodes()[0] - nodeURI := testnet.NodeURI{ - NodeID: node.GetID(), - URI: node.GetProcessContext().URI, - } - ethClient := e2e.Env.NewEthClient(nodeURI) - - ginkgo.By("initializing a transaction signer") - cChainID, err := ethClient.ChainID(e2e.DefaultContext()) - require.NoError(err) - signer := types.NewEIP155Signer(cChainID) - ecdsaKey := key.ToECDSA() - sign := func(tx *types.Transaction) *types.Transaction { - signedTx, err := types.SignTx(tx, signer, ecdsaKey) - require.NoError(err) - return signedTx - } - - var contractAddress common.Address - ginkgo.By("deploying an expensive contract", func() { - // Create transaction - nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) - require.NoError(err) - compiledContract := common.Hex2Bytes(hashingCompiledContract) - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - GasPrice: gasTip, - Gas: largeGasLimit, - Value: common.Big0, - Data: compiledContract, - }) - - // Send the transaction and wait for acceptance - signedTx := sign(tx) - receipt := e2e.SendEthTransaction(ethClient, signedTx) - - contractAddress = receipt.ContractAddress - }) - - var gasPrice *big.Int - ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { - // Evaluate the bytes representation of the contract - hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) - require.NoError(err) - contractData, err := hashingABI.Pack("hashIt") - require.NoError(err) - - var initialGasPrice *big.Int - e2e.Eventually(func() bool { - // Check the gas price - var err error - gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) - require.NoError(err) - if initialGasPrice == nil { - initialGasPrice = gasPrice - tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) - } else if gasPrice.Cmp(initialGasPrice) > 0 { - // Gas price has increased - tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) - return true - } - - // Create the transaction - nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) - require.NoError(err) - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - GasPrice: gasTip, - Gas: largeGasLimit, - To: &contractAddress, - Value: common.Big0, - Data: contractData, - }) - - // Send the transaction and wait for acceptance - signedTx := sign(tx) - _ = e2e.SendEthTransaction(ethClient, signedTx) - - // The gas price will be checked at the start of the next iteration - return false - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") - }) - - ginkgo.By("waiting for the gas price to decrease...", func() { - initialGasPrice := gasPrice - e2e.Eventually(func() bool { - var err error - gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) - require.NoError(err) - tests.Outf("{{blue}}.{{/}}") - return initialGasPrice.Cmp(gasPrice) > 0 - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") - tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) - }) - - ginkgo.By("sending funds at the current gas price", func() { - // Create a recipient address - recipientKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - recipientEthAddress := evm.GetEthAddress(recipientKey) - - // Create transaction - nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) - require.NoError(err) - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - GasPrice: gasPrice, - Gas: e2e.DefaultGasLimit, - To: &recipientEthAddress, - Value: common.Big0, - }) - - // Send the transaction and wait for acceptance - signedTx := sign(tx) - _ = e2e.SendEthTransaction(ethClient, signedTx) - }) - - e2e.CheckBootstrapIsPossible(privateNetwork) - }) -}) +// import ( +// "math/big" +// "strings" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/stretchr/testify/require" + +// "github.com/ethereum/go-ethereum/accounts/abi" +// "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/coreth/core/types" +// "github.com/ava-labs/coreth/params" +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/tests" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/tests/fixture/testnet" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// ) + +// // This test uses the compiled bin for `hashing.sol` as +// // well as its ABI contained in `hashing_contract.go`. + +// var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { +// require := require.New(ginkgo.GinkgoT()) + +// // Need a gas limit much larger than the standard 21_000 to enable +// // the contract to induce a gas price increase +// const largeGasLimit = uint64(8_000_000) + +// // TODO(marun) What is the significance of this value? +// gasTip := big.NewInt(1000 * params.GWei) + +// ginkgo.It("should ensure that the gas price is affected by load", func() { +// ginkgo.By("creating a new private network to ensure isolation from other tests") +// privateNetwork := e2e.Env.NewPrivateNetwork() + +// ginkgo.By("allocating a pre-funded key") +// key := privateNetwork.GetConfig().FundedKeys[0] +// ethAddress := evm.GetEthAddress(key) + +// ginkgo.By("initializing a coreth client") +// node := privateNetwork.GetNodes()[0] +// nodeURI := testnet.NodeURI{ +// NodeID: node.GetID(), +// URI: node.GetProcessContext().URI, +// } +// ethClient := e2e.Env.NewEthClient(nodeURI) + +// ginkgo.By("initializing a transaction signer") +// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) +// require.NoError(err) +// signer := types.NewEIP155Signer(cChainID) +// ecdsaKey := key.ToECDSA() +// sign := func(tx *types.Transaction) *types.Transaction { +// signedTx, err := types.SignTx(tx, signer, ecdsaKey) +// require.NoError(err) +// return signedTx +// } + +// var contractAddress common.Address +// ginkgo.By("deploying an expensive contract", func() { +// // Create transaction +// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) +// require.NoError(err) +// compiledContract := common.Hex2Bytes(hashingCompiledContract) +// tx := types.NewTx(&types.LegacyTx{ +// Nonce: nonce, +// GasPrice: gasTip, +// Gas: largeGasLimit, +// Value: common.Big0, +// Data: compiledContract, +// }) + +// // Send the transaction and wait for acceptance +// signedTx := sign(tx) +// receipt := e2e.SendEthTransaction(ethClient, signedTx) + +// contractAddress = receipt.ContractAddress +// }) + +// var gasPrice *big.Int +// ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { +// // Evaluate the bytes representation of the contract +// hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) +// require.NoError(err) +// contractData, err := hashingABI.Pack("hashIt") +// require.NoError(err) + +// var initialGasPrice *big.Int +// e2e.Eventually(func() bool { +// // Check the gas price +// var err error +// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) +// require.NoError(err) +// if initialGasPrice == nil { +// initialGasPrice = gasPrice +// tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) +// } else if gasPrice.Cmp(initialGasPrice) > 0 { +// // Gas price has increased +// tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) +// return true +// } + +// // Create the transaction +// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) +// require.NoError(err) +// tx := types.NewTx(&types.LegacyTx{ +// Nonce: nonce, +// GasPrice: gasTip, +// Gas: largeGasLimit, +// To: &contractAddress, +// Value: common.Big0, +// Data: contractData, +// }) + +// // Send the transaction and wait for acceptance +// signedTx := sign(tx) +// _ = e2e.SendEthTransaction(ethClient, signedTx) + +// // The gas price will be checked at the start of the next iteration +// return false +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") +// }) + +// ginkgo.By("waiting for the gas price to decrease...", func() { +// initialGasPrice := gasPrice +// e2e.Eventually(func() bool { +// var err error +// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) +// require.NoError(err) +// tests.Outf("{{blue}}.{{/}}") +// return initialGasPrice.Cmp(gasPrice) > 0 +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") +// tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) +// }) + +// ginkgo.By("sending funds at the current gas price", func() { +// // Create a recipient address +// recipientKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) +// recipientEthAddress := evm.GetEthAddress(recipientKey) + +// // Create transaction +// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) +// require.NoError(err) +// tx := types.NewTx(&types.LegacyTx{ +// Nonce: nonce, +// GasPrice: gasPrice, +// Gas: e2e.DefaultGasLimit, +// To: &recipientEthAddress, +// Value: common.Big0, +// }) + +// // Send the transaction and wait for acceptance +// signedTx := sign(tx) +// _ = e2e.SendEthTransaction(ethClient, signedTx) +// }) + +// e2e.CheckBootstrapIsPossible(privateNetwork) +// }) +// }) diff --git a/tests/e2e/c/interchain_workflow.go b/tests/e2e/c/interchain_workflow.go index 8bed85eb1bd9..d13c4b8db1ce 100644 --- a/tests/e2e/c/interchain_workflow.go +++ b/tests/e2e/c/interchain_workflow.go @@ -3,163 +3,163 @@ package c -import ( - "math/big" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/coreth/core/types" - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { - require := require.New(ginkgo.GinkgoT()) - - const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer - - ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { - ginkgo.By("initializing a new eth client") - // Select a random node URI to use for both the eth client and - // the wallet to avoid having to verify that all nodes are at - // the same height before initializing the wallet. - nodeURI := e2e.Env.GetRandomNodeURI() - ethClient := e2e.Env.NewEthClient(nodeURI) - - ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") - senderKey := e2e.Env.AllocateFundedKey() - senderEthAddress := evm.GetEthAddress(senderKey) - recipientKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - recipientEthAddress := evm.GetEthAddress(recipientKey) - - ginkgo.By("sending funds from one address to another on the C-Chain", func() { - // Create transaction - acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) - require.NoError(err) - gasPrice := e2e.SuggestGasPrice(ethClient) - tx := types.NewTransaction( - acceptedNonce, - recipientEthAddress, - big.NewInt(int64(txAmount)), - e2e.DefaultGasLimit, - gasPrice, - nil, - ) - - // Sign transaction - cChainID, err := ethClient.ChainID(e2e.DefaultContext()) - require.NoError(err) - signer := types.NewEIP155Signer(cChainID) - signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) - require.NoError(err) - - _ = e2e.SendEthTransaction(ethClient, signedTx) - - ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") - e2e.Eventually(func() bool { - balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) - require.NoError(err) - return balance.Cmp(big.NewInt(0)) > 0 - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") - }) - - // Wallet must be initialized after sending funds on the - // C-Chain with the same node URI to ensure wallet state - // matches on-chain state. - ginkgo.By("initializing a keychain and associated wallet") - keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) - baseWallet := e2e.Env.NewWallet(keychain, nodeURI) - xWallet := baseWallet.X() - cWallet := baseWallet.C() - pWallet := baseWallet.P() - - ginkgo.By("defining common configuration") - avaxAssetID := xWallet.AVAXAssetID() - // Use the same owner for import funds to X-Chain and P-Chain - recipientOwner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - recipientKey.Address(), - }, - } - // Use the same outputs for both X-Chain and P-Chain exports - exportOutputs := []*secp256k1fx.TransferOutput{ - { - Amt: txAmount, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - keychain.Keys[0].Address(), - }, - }, - }, - } - - ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { - _, err := cWallet.IssueExportTx( - xWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { - _, err := xWallet.IssueImportTx( - cWallet.BlockchainID(), - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { - balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { - _, err := cWallet.IssueExportTx( - constants.PlatformChainID, - exportOutputs, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { - _, err = pWallet.IssueImportTx( - cWallet.BlockchainID(), - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { - balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) - }) -}) +// import ( +// "math/big" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/stretchr/testify/require" + +// "github.com/ava-labs/coreth/core/types" +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { +// require := require.New(ginkgo.GinkgoT()) + +// const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer + +// ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { +// ginkgo.By("initializing a new eth client") +// // Select a random node URI to use for both the eth client and +// // the wallet to avoid having to verify that all nodes are at +// // the same height before initializing the wallet. +// nodeURI := e2e.Env.GetRandomNodeURI() +// ethClient := e2e.Env.NewEthClient(nodeURI) + +// ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") +// senderKey := e2e.Env.AllocateFundedKey() +// senderEthAddress := evm.GetEthAddress(senderKey) +// recipientKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) +// recipientEthAddress := evm.GetEthAddress(recipientKey) + +// ginkgo.By("sending funds from one address to another on the C-Chain", func() { +// // Create transaction +// acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) +// require.NoError(err) +// gasPrice := e2e.SuggestGasPrice(ethClient) +// tx := types.NewTransaction( +// acceptedNonce, +// recipientEthAddress, +// big.NewInt(int64(txAmount)), +// e2e.DefaultGasLimit, +// gasPrice, +// nil, +// ) + +// // Sign transaction +// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) +// require.NoError(err) +// signer := types.NewEIP155Signer(cChainID) +// signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) +// require.NoError(err) + +// _ = e2e.SendEthTransaction(ethClient, signedTx) + +// ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") +// e2e.Eventually(func() bool { +// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) +// require.NoError(err) +// return balance.Cmp(big.NewInt(0)) > 0 +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") +// }) + +// // Wallet must be initialized after sending funds on the +// // C-Chain with the same node URI to ensure wallet state +// // matches on-chain state. +// ginkgo.By("initializing a keychain and associated wallet") +// keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) +// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) +// xWallet := baseWallet.X() +// cWallet := baseWallet.C() +// pWallet := baseWallet.P() + +// ginkgo.By("defining common configuration") +// avaxAssetID := xWallet.AVAXAssetID() +// // Use the same owner for import funds to X-Chain and P-Chain +// recipientOwner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// recipientKey.Address(), +// }, +// } +// // Use the same outputs for both X-Chain and P-Chain exports +// exportOutputs := []*secp256k1fx.TransferOutput{ +// { +// Amt: txAmount, +// OutputOwners: secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// keychain.Keys[0].Address(), +// }, +// }, +// }, +// } + +// ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { +// _, err := cWallet.IssueExportTx( +// xWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { +// _, err := xWallet.IssueImportTx( +// cWallet.BlockchainID(), +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { +// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { +// _, err := cWallet.IssueExportTx( +// constants.PlatformChainID, +// exportOutputs, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { +// _, err = pWallet.IssueImportTx( +// cWallet.BlockchainID(), +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { +// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) +// }) +// }) diff --git a/tests/e2e/e2e.go b/tests/e2e/e2e.go index 130f33f1197c..e69e244d3ee3 100644 --- a/tests/e2e/e2e.go +++ b/tests/e2e/e2e.go @@ -7,22 +7,25 @@ package e2e import ( "context" "encoding/json" - "errors" - "fmt" - "math/big" + "path/filepath" + + // "errors" + // "fmt" + // "math/big" "math/rand" "os" - "path/filepath" - "strings" + + // "path/filepath" + // "strings" "time" ginkgo "github.com/onsi/ginkgo/v2" "github.com/stretchr/testify/require" - "github.com/ava-labs/coreth/core/types" - "github.com/ava-labs/coreth/ethclient" - "github.com/ava-labs/coreth/interfaces" + // "github.com/ava-labs/coreth/core/types" + // "github.com/ava-labs/coreth/ethclient" + // "github.com/ava-labs/coreth/interfaces" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/tests" @@ -134,7 +137,7 @@ func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain, nodeURI tes baseWallet, err := primary.MakeWallet(DefaultContext(), &primary.WalletConfig{ URI: nodeURI.URI, AVAXKeychain: keychain, - EthKeychain: keychain, + // EthKeychain: keychain, }) te.require.NoError(err) return primary.NewWalletWithOptions( @@ -147,16 +150,16 @@ func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain, nodeURI tes ) } -// Create a new eth client targeting the specified node URI. -// TODO(marun) Make this a regular function. -func (te *TestEnvironment) NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { - tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) - nodeAddress := strings.Split(nodeURI.URI, "//")[1] - uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) - client, err := ethclient.Dial(uri) - te.require.NoError(err) - return client -} +// // Create a new eth client targeting the specified node URI. +// // TODO(marun) Make this a regular function. +// func (te *TestEnvironment) NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { +// tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) +// nodeAddress := strings.Split(nodeURI.URI, "//")[1] +// uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) +// client, err := ethclient.Dial(uri) +// te.require.NoError(err) +// return client +// } // Create a new private network that is not shared with other tests. func (te *TestEnvironment) NewPrivateNetwork() testnet.Network { @@ -231,49 +234,49 @@ func WaitForHealthy(node testnet.Node) { require.NoError(ginkgo.GinkgoT(), testnet.WaitForHealthy(DefaultContext(), node)) } -// Sends an eth transaction, waits for the transaction receipt to be issued -// and checks that the receipt indicates success. -func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { - require := require.New(ginkgo.GinkgoT()) - - txID := signedTx.Hash() - tests.Outf(" sending eth transaction with ID: %s\n", txID) - - require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) - - // Wait for the receipt - var receipt *types.Receipt - Eventually(func() bool { - var err error - receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) - if errors.Is(err, interfaces.NotFound) { - return false // Transaction is still pending - } - require.NoError(err) - return true - }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") - - require.Equal(receipt.Status, types.ReceiptStatusSuccessful) - return receipt -} - -// Determines the suggested gas price for the configured client that will -// maximize the chances of transaction acceptance. -func SuggestGasPrice(ethClient ethclient.Client) *big.Int { - gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) - require.NoError(ginkgo.GinkgoT(), err) - // Double the suggested gas price to maximize the chances of - // acceptance. Maybe this can be revisited pending resolution of - // https://github.com/ava-labs/coreth/issues/314. - gasPrice.Add(gasPrice, gasPrice) - return gasPrice -} - -// Helper simplifying use via an option of a gas price appropriate for testing. -func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { - baseFee := SuggestGasPrice(ethClient) - return common.WithBaseFee(baseFee) -} +// // Sends an eth transaction, waits for the transaction receipt to be issued +// // and checks that the receipt indicates success. +// func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { +// require := require.New(ginkgo.GinkgoT()) + +// txID := signedTx.Hash() +// tests.Outf(" sending eth transaction with ID: %s\n", txID) + +// require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) + +// // Wait for the receipt +// var receipt *types.Receipt +// Eventually(func() bool { +// var err error +// receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) +// if errors.Is(err, interfaces.NotFound) { +// return false // Transaction is still pending +// } +// require.NoError(err) +// return true +// }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") + +// require.Equal(receipt.Status, types.ReceiptStatusSuccessful) +// return receipt +// } + +// // Determines the suggested gas price for the configured client that will +// // maximize the chances of transaction acceptance. +// func SuggestGasPrice(ethClient ethclient.Client) *big.Int { +// gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) +// require.NoError(ginkgo.GinkgoT(), err) +// // Double the suggested gas price to maximize the chances of +// // acceptance. Maybe this can be revisited pending resolution of +// // https://github.com/ava-labs/coreth/issues/314. +// gasPrice.Add(gasPrice, gasPrice) +// return gasPrice +// } + +// // Helper simplifying use via an option of a gas price appropriate for testing. +// func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { +// baseFee := SuggestGasPrice(ethClient) +// return common.WithBaseFee(baseFee) +// } // Verify that a new node can bootstrap into the network. func CheckBootstrapIsPossible(network testnet.Network) { diff --git a/tests/e2e/p/interchain_workflow.go b/tests/e2e/p/interchain_workflow.go index 729418adbd97..d3715c254e90 100644 --- a/tests/e2e/p/interchain_workflow.go +++ b/tests/e2e/p/interchain_workflow.go @@ -3,225 +3,225 @@ package p -import ( - "math/big" - "time" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/spf13/cast" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/api/info" - "github.com/ava-labs/avalanchego/config" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/tests/fixture/testnet" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/platformvm/reward" - "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { - require := require.New(ginkgo.GinkgoT()) - - const ( - transferAmount = 10 * units.Avax - weight = 2_000 * units.Avax // Used for both validation and delegation - ) - - ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { - network := e2e.Env.GetNetwork() - - ginkgo.By("checking that the network has a compatible minimum stake duration", func() { - minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) - require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) - }) - - ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") - recipientKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - keychain := e2e.Env.NewKeychain(1) - keychain.Add(recipientKey) - nodeURI := e2e.Env.GetRandomNodeURI() - baseWallet := e2e.Env.NewWallet(keychain, nodeURI) - xWallet := baseWallet.X() - cWallet := baseWallet.C() - pWallet := baseWallet.P() - - ginkgo.By("defining common configuration") - recipientEthAddress := evm.GetEthAddress(recipientKey) - avaxAssetID := xWallet.AVAXAssetID() - // Use the same owner for sending to X-Chain and importing funds to P-Chain - recipientOwner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - recipientKey.Address(), - }, - } - // Use the same outputs for both X-Chain and C-Chain exports - exportOutputs := []*avax.TransferableOutput{ - { - Asset: avax.Asset{ - ID: avaxAssetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: transferAmount, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - keychain.Keys[0].Address(), - }, - }, - }, - }, - } - - ginkgo.By("adding new node and waiting for it to report healthy") - node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) - e2e.WaitForHealthy(node) - - ginkgo.By("retrieving new node's id and pop") - infoClient := info.NewClient(node.GetProcessContext().URI) - nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) - require.NoError(err) - - ginkgo.By("adding the new node as a validator", func() { - startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) - // Validation duration doesn't actually matter to this - // test - it is only ensuring that adding a validator - // doesn't break interchain transfer. - endTime := startTime.Add(30 * time.Second) - - rewardKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - - const ( - delegationPercent = 0.10 // 10% - delegationShare = reward.PercentDenominator * delegationPercent - ) - - _, err = pWallet.IssueAddPermissionlessValidatorTx( - &txs.SubnetValidator{ - Validator: txs.Validator{ - NodeID: nodeID, - Start: uint64(startTime.Unix()), - End: uint64(endTime.Unix()), - Wght: weight, - }, - Subnet: constants.PrimaryNetworkID, - }, - nodePOP, - pWallet.AVAXAssetID(), - &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{rewardKey.Address()}, - }, - &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{rewardKey.Address()}, - }, - delegationShare, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("adding a delegator to the new node", func() { - startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) - // Delegation duration doesn't actually matter to this - // test - it is only ensuring that adding a delegator - // doesn't break interchain transfer. - endTime := startTime.Add(15 * time.Second) - - rewardKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - - _, err = pWallet.IssueAddPermissionlessDelegatorTx( - &txs.SubnetValidator{ - Validator: txs.Validator{ - NodeID: nodeID, - Start: uint64(startTime.Unix()), - End: uint64(endTime.Unix()), - Wght: weight, - }, - Subnet: constants.PrimaryNetworkID, - }, - pWallet.AVAXAssetID(), - &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{rewardKey.Address()}, - }, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { - _, err := pWallet.IssueExportTx( - xWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { - _, err := xWallet.IssueImportTx( - constants.PlatformChainID, - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { - balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { - _, err := pWallet.IssueExportTx( - cWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("initializing a new eth client") - ethClient := e2e.Env.NewEthClient(nodeURI) - - ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { - _, err := cWallet.IssueImportTx( - constants.PlatformChainID, - recipientEthAddress, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") - balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) - require.NoError(err) - require.Positive(balance.Cmp(big.NewInt(0))) - - ginkgo.By("stopping validator node to free up resources for a bootstrap check") - require.NoError(node.Stop()) - - e2e.CheckBootstrapIsPossible(network) - }) -}) +// import ( +// "math/big" +// "time" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/spf13/cast" + +// "github.com/stretchr/testify/require" + +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/api/info" +// "github.com/ava-labs/avalanchego/config" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/tests/fixture/testnet" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/platformvm/reward" +// "github.com/ava-labs/avalanchego/vms/platformvm/txs" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { +// require := require.New(ginkgo.GinkgoT()) + +// const ( +// transferAmount = 10 * units.Avax +// weight = 2_000 * units.Avax // Used for both validation and delegation +// ) + +// ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { +// network := e2e.Env.GetNetwork() + +// ginkgo.By("checking that the network has a compatible minimum stake duration", func() { +// minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) +// require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) +// }) + +// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") +// recipientKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) +// keychain := e2e.Env.NewKeychain(1) +// keychain.Add(recipientKey) +// nodeURI := e2e.Env.GetRandomNodeURI() +// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) +// xWallet := baseWallet.X() +// cWallet := baseWallet.C() +// pWallet := baseWallet.P() + +// ginkgo.By("defining common configuration") +// recipientEthAddress := evm.GetEthAddress(recipientKey) +// avaxAssetID := xWallet.AVAXAssetID() +// // Use the same owner for sending to X-Chain and importing funds to P-Chain +// recipientOwner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// recipientKey.Address(), +// }, +// } +// // Use the same outputs for both X-Chain and C-Chain exports +// exportOutputs := []*avax.TransferableOutput{ +// { +// Asset: avax.Asset{ +// ID: avaxAssetID, +// }, +// Out: &secp256k1fx.TransferOutput{ +// Amt: transferAmount, +// OutputOwners: secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// keychain.Keys[0].Address(), +// }, +// }, +// }, +// }, +// } + +// ginkgo.By("adding new node and waiting for it to report healthy") +// node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) +// e2e.WaitForHealthy(node) + +// ginkgo.By("retrieving new node's id and pop") +// infoClient := info.NewClient(node.GetProcessContext().URI) +// nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) +// require.NoError(err) + +// ginkgo.By("adding the new node as a validator", func() { +// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) +// // Validation duration doesn't actually matter to this +// // test - it is only ensuring that adding a validator +// // doesn't break interchain transfer. +// endTime := startTime.Add(30 * time.Second) + +// rewardKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) + +// const ( +// delegationPercent = 0.10 // 10% +// delegationShare = reward.PercentDenominator * delegationPercent +// ) + +// _, err = pWallet.IssueAddPermissionlessValidatorTx( +// &txs.SubnetValidator{ +// Validator: txs.Validator{ +// NodeID: nodeID, +// Start: uint64(startTime.Unix()), +// End: uint64(endTime.Unix()), +// Wght: weight, +// }, +// Subnet: constants.PrimaryNetworkID, +// }, +// nodePOP, +// pWallet.AVAXAssetID(), +// &secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{rewardKey.Address()}, +// }, +// &secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{rewardKey.Address()}, +// }, +// delegationShare, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("adding a delegator to the new node", func() { +// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) +// // Delegation duration doesn't actually matter to this +// // test - it is only ensuring that adding a delegator +// // doesn't break interchain transfer. +// endTime := startTime.Add(15 * time.Second) + +// rewardKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) + +// _, err = pWallet.IssueAddPermissionlessDelegatorTx( +// &txs.SubnetValidator{ +// Validator: txs.Validator{ +// NodeID: nodeID, +// Start: uint64(startTime.Unix()), +// End: uint64(endTime.Unix()), +// Wght: weight, +// }, +// Subnet: constants.PrimaryNetworkID, +// }, +// pWallet.AVAXAssetID(), +// &secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{rewardKey.Address()}, +// }, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { +// _, err := pWallet.IssueExportTx( +// xWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { +// _, err := xWallet.IssueImportTx( +// constants.PlatformChainID, +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { +// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { +// _, err := pWallet.IssueExportTx( +// cWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("initializing a new eth client") +// ethClient := e2e.Env.NewEthClient(nodeURI) + +// ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { +// _, err := cWallet.IssueImportTx( +// constants.PlatformChainID, +// recipientEthAddress, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") +// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) +// require.NoError(err) +// require.Positive(balance.Cmp(big.NewInt(0))) + +// ginkgo.By("stopping validator node to free up resources for a bootstrap check") +// require.NoError(node.Stop()) + +// e2e.CheckBootstrapIsPossible(network) +// }) +// }) diff --git a/tests/e2e/x/interchain_workflow.go b/tests/e2e/x/interchain_workflow.go index 6d335199b5b9..3b7a4c988405 100644 --- a/tests/e2e/x/interchain_workflow.go +++ b/tests/e2e/x/interchain_workflow.go @@ -3,151 +3,151 @@ package x -import ( - "math/big" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { - require := require.New(ginkgo.GinkgoT()) - - const transferAmount = 10 * units.Avax - - ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { - nodeURI := e2e.Env.GetRandomNodeURI() - - ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") - recipientKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - keychain := e2e.Env.NewKeychain(1) - keychain.Add(recipientKey) - baseWallet := e2e.Env.NewWallet(keychain, nodeURI) - xWallet := baseWallet.X() - cWallet := baseWallet.C() - pWallet := baseWallet.P() - - ginkgo.By("defining common configuration") - recipientEthAddress := evm.GetEthAddress(recipientKey) - avaxAssetID := xWallet.AVAXAssetID() - // Use the same owner for sending to X-Chain and importing funds to P-Chain - recipientOwner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - recipientKey.Address(), - }, - } - // Use the same outputs for both C-Chain and P-Chain exports - exportOutputs := []*avax.TransferableOutput{ - { - Asset: avax.Asset{ - ID: avaxAssetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: transferAmount, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - keychain.Keys[0].Address(), - }, - }, - }, - }, - } - - ginkgo.By("sending funds from one address to another on the X-Chain", func() { - _, err = xWallet.IssueBaseTx( - []*avax.TransferableOutput{{ - Asset: avax.Asset{ - ID: avaxAssetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: transferAmount, - OutputOwners: recipientOwner, - }, - }}, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { - balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { - _, err := xWallet.IssueExportTx( - cWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("initializing a new eth client") - ethClient := e2e.Env.NewEthClient(nodeURI) - - ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { - _, err := cWallet.IssueImportTx( - xWallet.BlockchainID(), - recipientEthAddress, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") - e2e.Eventually(func() bool { - balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) - require.NoError(err) - return balance.Cmp(big.NewInt(0)) > 0 - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") - - ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { - _, err := xWallet.IssueExportTx( - constants.PlatformChainID, - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { - _, err := pWallet.IssueImportTx( - xWallet.BlockchainID(), - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { - balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) - }) -}) +// import ( +// "math/big" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/stretchr/testify/require" + +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { +// require := require.New(ginkgo.GinkgoT()) + +// const transferAmount = 10 * units.Avax + +// ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { +// nodeURI := e2e.Env.GetRandomNodeURI() + +// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") +// recipientKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) +// keychain := e2e.Env.NewKeychain(1) +// keychain.Add(recipientKey) +// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) +// xWallet := baseWallet.X() +// cWallet := baseWallet.C() +// pWallet := baseWallet.P() + +// ginkgo.By("defining common configuration") +// recipientEthAddress := evm.GetEthAddress(recipientKey) +// avaxAssetID := xWallet.AVAXAssetID() +// // Use the same owner for sending to X-Chain and importing funds to P-Chain +// recipientOwner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// recipientKey.Address(), +// }, +// } +// // Use the same outputs for both C-Chain and P-Chain exports +// exportOutputs := []*avax.TransferableOutput{ +// { +// Asset: avax.Asset{ +// ID: avaxAssetID, +// }, +// Out: &secp256k1fx.TransferOutput{ +// Amt: transferAmount, +// OutputOwners: secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// keychain.Keys[0].Address(), +// }, +// }, +// }, +// }, +// } + +// ginkgo.By("sending funds from one address to another on the X-Chain", func() { +// _, err = xWallet.IssueBaseTx( +// []*avax.TransferableOutput{{ +// Asset: avax.Asset{ +// ID: avaxAssetID, +// }, +// Out: &secp256k1fx.TransferOutput{ +// Amt: transferAmount, +// OutputOwners: recipientOwner, +// }, +// }}, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { +// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { +// _, err := xWallet.IssueExportTx( +// cWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("initializing a new eth client") +// ethClient := e2e.Env.NewEthClient(nodeURI) + +// ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { +// _, err := cWallet.IssueImportTx( +// xWallet.BlockchainID(), +// recipientEthAddress, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") +// e2e.Eventually(func() bool { +// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) +// require.NoError(err) +// return balance.Cmp(big.NewInt(0)) > 0 +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") + +// ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { +// _, err := xWallet.IssueExportTx( +// constants.PlatformChainID, +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { +// _, err := pWallet.IssueImportTx( +// xWallet.BlockchainID(), +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { +// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) +// }) +// }) diff --git a/tests/fixture/testnet/config.go b/tests/fixture/testnet/config.go index 425aa646a690..7130ad290ab5 100644 --- a/tests/fixture/testnet/config.go +++ b/tests/fixture/testnet/config.go @@ -15,9 +15,9 @@ import ( "github.com/spf13/cast" - "github.com/ava-labs/coreth/core" - "github.com/ava-labs/coreth/params" - "github.com/ava-labs/coreth/plugin/evm" + // "github.com/ava-labs/coreth/core" + // "github.com/ava-labs/coreth/params" + // "github.com/ava-labs/coreth/plugin/evm" "github.com/ava-labs/avalanchego/config" "github.com/ava-labs/avalanchego/genesis" @@ -143,15 +143,15 @@ func (c *NetworkConfig) EnsureGenesis(networkID uint32, validatorIDs []ids.NodeI // Ensure pre-funded keys have arbitrary large balances on both chains to support testing xChainBalances := make(XChainBalanceMap, len(c.FundedKeys)) - cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) + // cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) for _, key := range c.FundedKeys { xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount - cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ - Balance: DefaultFundedKeyCChainAmount, - } + // cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ + // Balance: DefaultFundedKeyCChainAmount, + // } } - genesis, err := NewTestGenesis(networkID, xChainBalances, cChainBalances, validatorIDs) + genesis, err := NewTestGenesis(networkID, xChainBalances /*cChainBalances,*/, validatorIDs) if err != nil { return err } @@ -311,7 +311,7 @@ type XChainBalanceMap map[ids.ShortID]uint64 func NewTestGenesis( networkID uint32, xChainBalances XChainBalanceMap, - cChainBalances core.GenesisAlloc, + // cChainBalances core.GenesisAlloc, validatorIDs []ids.NodeID, ) (*genesis.UnparsedConfig, error) { // Validate inputs @@ -322,7 +322,7 @@ func NewTestGenesis( if len(validatorIDs) == 0 { return nil, errMissingValidatorsForGenesis } - if len(xChainBalances) == 0 || len(cChainBalances) == 0 { + if len(xChainBalances) == 0 /*|| len(cChainBalances) == 0*/ { return nil, errMissingBalancesForGenesis } @@ -394,20 +394,20 @@ func NewTestGenesis( ) } - // Define C-Chain genesis - cChainGenesis := &core.Genesis{ - Config: ¶ms.ChainConfig{ - ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary - }, - Difficulty: big.NewInt(0), // Difficulty is a mandatory field - GasLimit: DefaultGasLimit, - Alloc: cChainBalances, - } - cChainGenesisBytes, err := json.Marshal(cChainGenesis) - if err != nil { - return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) - } - config.CChainGenesis = string(cChainGenesisBytes) + // // Define C-Chain genesis + // cChainGenesis := &core.Genesis{ + // Config: ¶ms.ChainConfig{ + // ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary + // }, + // Difficulty: big.NewInt(0), // Difficulty is a mandatory field + // GasLimit: DefaultGasLimit, + // Alloc: cChainBalances, + // } + // cChainGenesisBytes, err := json.Marshal(cChainGenesis) + // if err != nil { + // return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) + // } + // config.CChainGenesis = string(cChainGenesisBytes) // Give staking rewards for initial validators to a random address. Any testing of staking rewards // will be easier to perform with nodes other than the initial validators since the timing of diff --git a/vms/example/xsvm/cmd/chain/create/cmd.go b/vms/example/xsvm/cmd/chain/create/cmd.go index 1f00491a4ce6..043b4298dcdf 100644 --- a/vms/example/xsvm/cmd/chain/create/cmd.go +++ b/vms/example/xsvm/cmd/chain/create/cmd.go @@ -42,9 +42,9 @@ func createFunc(c *cobra.Command, args []string) error { // that [uri] is hosting. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: config.URI, - AVAXKeychain: kc, - EthKeychain: kc, + URI: config.URI, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(config.SubnetID), }) if err != nil { diff --git a/wallet/chain/c/backend.go b/wallet/chain/c/backend.go index 0a735116b646..b88c8c643bc3 100644 --- a/wallet/chain/c/backend.go +++ b/wallet/chain/c/backend.go @@ -3,153 +3,153 @@ package c -import ( - "errors" - "fmt" - "math/big" - "sync" - - stdcontext "context" - - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/utils/math" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var ( - _ Backend = (*backend)(nil) - - errUnknownTxType = errors.New("unknown tx type") -) - -// Backend defines the full interface required to support a C-chain wallet. -type Backend interface { - common.ChainUTXOs - BuilderBackend - SignerBackend - - AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error -} - -type backend struct { - Context - common.ChainUTXOs - - accountsLock sync.RWMutex - accounts map[ethcommon.Address]*Account -} - -type Account struct { - Balance *big.Int - Nonce uint64 -} - -func NewBackend( - ctx Context, - utxos common.ChainUTXOs, - accounts map[ethcommon.Address]*Account, -) Backend { - return &backend{ - Context: ctx, - ChainUTXOs: utxos, - accounts: accounts, - } -} - -func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { - switch tx := tx.UnsignedAtomicTx.(type) { - case *evm.UnsignedImportTx: - for _, input := range tx.ImportedInputs { - utxoID := input.InputID() - if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { - return err - } - } - - b.accountsLock.Lock() - defer b.accountsLock.Unlock() - - for _, output := range tx.Outs { - account, ok := b.accounts[output.Address] - if !ok { - continue - } - - balance := new(big.Int).SetUint64(output.Amount) - balance.Mul(balance, avaxConversionRate) - account.Balance.Add(account.Balance, balance) - } - case *evm.UnsignedExportTx: - txID := tx.ID() - for i, out := range tx.ExportedOutputs { - err := b.AddUTXO( - ctx, - tx.DestinationChain, - &avax.UTXO{ - UTXOID: avax.UTXOID{ - TxID: txID, - OutputIndex: uint32(i), - }, - Asset: avax.Asset{ID: out.AssetID()}, - Out: out.Out, - }, - ) - if err != nil { - return err - } - } - - b.accountsLock.Lock() - defer b.accountsLock.Unlock() - - for _, input := range tx.Ins { - account, ok := b.accounts[input.Address] - if !ok { - continue - } - - balance := new(big.Int).SetUint64(input.Amount) - balance.Mul(balance, avaxConversionRate) - if account.Balance.Cmp(balance) == -1 { - return errInsufficientFunds - } - account.Balance.Sub(account.Balance, balance) - - newNonce, err := math.Add64(input.Nonce, 1) - if err != nil { - return err - } - account.Nonce = newNonce - } - default: - return fmt.Errorf("%w: %T", errUnknownTxType, tx) - } - return nil -} - -func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { - b.accountsLock.RLock() - defer b.accountsLock.RUnlock() - - account, exists := b.accounts[addr] - if !exists { - return nil, database.ErrNotFound - } - return account.Balance, nil -} - -func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { - b.accountsLock.RLock() - defer b.accountsLock.RUnlock() - - account, exists := b.accounts[addr] - if !exists { - return 0, database.ErrNotFound - } - return account.Nonce, nil -} +// import ( +// "errors" +// "fmt" +// "math/big" +// "sync" + +// stdcontext "context" + +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/database" +// "github.com/ava-labs/avalanchego/utils/math" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var ( +// _ Backend = (*backend)(nil) + +// errUnknownTxType = errors.New("unknown tx type") +// ) + +// // Backend defines the full interface required to support a C-chain wallet. +// type Backend interface { +// common.ChainUTXOs +// BuilderBackend +// SignerBackend + +// AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error +// } + +// type backend struct { +// Context +// common.ChainUTXOs + +// accountsLock sync.RWMutex +// accounts map[ethcommon.Address]*Account +// } + +// type Account struct { +// Balance *big.Int +// Nonce uint64 +// } + +// func NewBackend( +// ctx Context, +// utxos common.ChainUTXOs, +// accounts map[ethcommon.Address]*Account, +// ) Backend { +// return &backend{ +// Context: ctx, +// ChainUTXOs: utxos, +// accounts: accounts, +// } +// } + +// func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { +// switch tx := tx.UnsignedAtomicTx.(type) { +// case *evm.UnsignedImportTx: +// for _, input := range tx.ImportedInputs { +// utxoID := input.InputID() +// if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { +// return err +// } +// } + +// b.accountsLock.Lock() +// defer b.accountsLock.Unlock() + +// for _, output := range tx.Outs { +// account, ok := b.accounts[output.Address] +// if !ok { +// continue +// } + +// balance := new(big.Int).SetUint64(output.Amount) +// balance.Mul(balance, avaxConversionRate) +// account.Balance.Add(account.Balance, balance) +// } +// case *evm.UnsignedExportTx: +// txID := tx.ID() +// for i, out := range tx.ExportedOutputs { +// err := b.AddUTXO( +// ctx, +// tx.DestinationChain, +// &avax.UTXO{ +// UTXOID: avax.UTXOID{ +// TxID: txID, +// OutputIndex: uint32(i), +// }, +// Asset: avax.Asset{ID: out.AssetID()}, +// Out: out.Out, +// }, +// ) +// if err != nil { +// return err +// } +// } + +// b.accountsLock.Lock() +// defer b.accountsLock.Unlock() + +// for _, input := range tx.Ins { +// account, ok := b.accounts[input.Address] +// if !ok { +// continue +// } + +// balance := new(big.Int).SetUint64(input.Amount) +// balance.Mul(balance, avaxConversionRate) +// if account.Balance.Cmp(balance) == -1 { +// return errInsufficientFunds +// } +// account.Balance.Sub(account.Balance, balance) + +// newNonce, err := math.Add64(input.Nonce, 1) +// if err != nil { +// return err +// } +// account.Nonce = newNonce +// } +// default: +// return fmt.Errorf("%w: %T", errUnknownTxType, tx) +// } +// return nil +// } + +// func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { +// b.accountsLock.RLock() +// defer b.accountsLock.RUnlock() + +// account, exists := b.accounts[addr] +// if !exists { +// return nil, database.ErrNotFound +// } +// return account.Balance, nil +// } + +// func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { +// b.accountsLock.RLock() +// defer b.accountsLock.RUnlock() + +// account, exists := b.accounts[addr] +// if !exists { +// return 0, database.ErrNotFound +// } +// return account.Nonce, nil +// } diff --git a/wallet/chain/c/builder.go b/wallet/chain/c/builder.go index d2d088e88a53..c51d2647777e 100644 --- a/wallet/chain/c/builder.go +++ b/wallet/chain/c/builder.go @@ -3,399 +3,399 @@ package c -import ( - "errors" - "math/big" - - stdcontext "context" - - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils" - "github.com/ava-labs/avalanchego/utils/math" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -const avaxConversionRateInt = 1_000_000_000 - -var ( - _ Builder = (*builder)(nil) - - errInsufficientFunds = errors.New("insufficient funds") - - // avaxConversionRate is the conversion rate between the smallest - // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest - // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. - // - // This is only required for AVAX because the denomination of 1 AVAX is 9 - // decimal places on the X and P chains, but is 18 decimal places within the - // EVM. - avaxConversionRate = big.NewInt(avaxConversionRateInt) -) - -// Builder provides a convenient interface for building unsigned C-chain -// transactions. -type Builder interface { - // GetBalance calculates the amount of AVAX that this builder has control - // over. - GetBalance( - options ...common.Option, - ) (*big.Int, error) - - // GetImportableBalance calculates the amount of AVAX that this builder - // could import from the provided chain. - // - // - [chainID] specifies the chain the funds are from. - GetImportableBalance( - chainID ids.ID, - options ...common.Option, - ) (uint64, error) - - // NewImportTx creates an import transaction that attempts to consume all - // the available UTXOs and import the funds to [to]. - // - // - [chainID] specifies the chain to be importing funds from. - // - [to] specifies where to send the imported funds to. - // - [baseFee] specifies the fee price willing to be paid by this tx. - NewImportTx( - chainID ids.ID, - to ethcommon.Address, - baseFee *big.Int, - options ...common.Option, - ) (*evm.UnsignedImportTx, error) - - // NewExportTx creates an export transaction that attempts to send all the - // provided [outputs] to the requested [chainID]. - // - // - [chainID] specifies the chain to be exporting the funds to. - // - [outputs] specifies the outputs to send to the [chainID]. - // - [baseFee] specifies the fee price willing to be paid by this tx. - NewExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - baseFee *big.Int, - options ...common.Option, - ) (*evm.UnsignedExportTx, error) -} - -// BuilderBackend specifies the required information needed to build unsigned -// C-chain transactions. -type BuilderBackend interface { - Context - - UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) - Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) - Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) -} - -type builder struct { - avaxAddrs set.Set[ids.ShortID] - ethAddrs set.Set[ethcommon.Address] - backend BuilderBackend -} - -// NewBuilder returns a new transaction builder. -// -// - [avaxAddrs] is the set of addresses in the AVAX format that the builder -// assumes can be used when signing the transactions in the future. -// - [ethAddrs] is the set of addresses in the Eth format that the builder -// assumes can be used when signing the transactions in the future. -// - [backend] provides the required access to the chain's context and state -// to build out the transactions. -func NewBuilder( - avaxAddrs set.Set[ids.ShortID], - ethAddrs set.Set[ethcommon.Address], - backend BuilderBackend, -) Builder { - return &builder{ - avaxAddrs: avaxAddrs, - ethAddrs: ethAddrs, - backend: backend, - } -} - -func (b *builder) GetBalance( - options ...common.Option, -) (*big.Int, error) { - var ( - ops = common.NewOptions(options) - ctx = ops.Context() - addrs = ops.EthAddresses(b.ethAddrs) - totalBalance = new(big.Int) - ) - for addr := range addrs { - balance, err := b.backend.Balance(ctx, addr) - if err != nil { - return nil, err - } - totalBalance.Add(totalBalance, balance) - } - - return totalBalance, nil -} - -func (b *builder) GetImportableBalance( - chainID ids.ID, - options ...common.Option, -) (uint64, error) { - ops := common.NewOptions(options) - utxos, err := b.backend.UTXOs(ops.Context(), chainID) - if err != nil { - return 0, err - } - - var ( - addrs = ops.Addresses(b.avaxAddrs) - minIssuanceTime = ops.MinIssuanceTime() - avaxAssetID = b.backend.AVAXAssetID() - balance uint64 - ) - for _, utxo := range utxos { - amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) - if !ok { - continue - } - - newBalance, err := math.Add64(balance, amount) - if err != nil { - return 0, err - } - balance = newBalance - } - - return balance, nil -} - -func (b *builder) NewImportTx( - chainID ids.ID, - to ethcommon.Address, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedImportTx, error) { - ops := common.NewOptions(options) - utxos, err := b.backend.UTXOs(ops.Context(), chainID) - if err != nil { - return nil, err - } - - var ( - addrs = ops.Addresses(b.avaxAddrs) - minIssuanceTime = ops.MinIssuanceTime() - avaxAssetID = b.backend.AVAXAssetID() - - importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) - importedAmount uint64 - ) - for _, utxo := range utxos { - amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) - if !ok { - continue - } - - importedInputs = append(importedInputs, &avax.TransferableInput{ - UTXOID: utxo.UTXOID, - Asset: utxo.Asset, - In: &secp256k1fx.TransferInput{ - Amt: amount, - Input: secp256k1fx.Input{ - SigIndices: inputSigIndices, - }, - }, - }) - - newImportedAmount, err := math.Add64(importedAmount, amount) - if err != nil { - return nil, err - } - importedAmount = newImportedAmount - } - - utils.Sort(importedInputs) - tx := &evm.UnsignedImportTx{ - NetworkID: b.backend.NetworkID(), - BlockchainID: b.backend.BlockchainID(), - SourceChain: chainID, - ImportedInputs: importedInputs, - } - - // We must initialize the bytes of the tx to calculate the initial cost - wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} - if err := wrappedTx.Sign(evm.Codec, nil); err != nil { - return nil, err - } - - gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) - if err != nil { - return nil, err - } - gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas - - txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) - if err != nil { - return nil, err - } - - if importedAmount <= txFee { - return nil, errInsufficientFunds - } - - tx.Outs = []evm.EVMOutput{{ - Address: to, - Amount: importedAmount - txFee, - AssetID: avaxAssetID, - }} - return tx, nil -} - -func (b *builder) NewExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedExportTx, error) { - var ( - avaxAssetID = b.backend.AVAXAssetID() - exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) - exportedAmount uint64 - ) - for i, output := range outputs { - exportedOutputs[i] = &avax.TransferableOutput{ - Asset: avax.Asset{ID: avaxAssetID}, - Out: output, - } - - newExportedAmount, err := math.Add64(exportedAmount, output.Amt) - if err != nil { - return nil, err - } - exportedAmount = newExportedAmount - } - - avax.SortTransferableOutputs(exportedOutputs, evm.Codec) - tx := &evm.UnsignedExportTx{ - NetworkID: b.backend.NetworkID(), - BlockchainID: b.backend.BlockchainID(), - DestinationChain: chainID, - ExportedOutputs: exportedOutputs, - } - - // We must initialize the bytes of the tx to calculate the initial cost - wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} - if err := wrappedTx.Sign(evm.Codec, nil); err != nil { - return nil, err - } - - cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) - if err != nil { - return nil, err - } - - initialFee, err := evm.CalculateDynamicFee(cost, baseFee) - if err != nil { - return nil, err - } - - amountToConsume, err := math.Add64(exportedAmount, initialFee) - if err != nil { - return nil, err - } - - var ( - ops = common.NewOptions(options) - ctx = ops.Context() - addrs = ops.EthAddresses(b.ethAddrs) - inputs = make([]evm.EVMInput, 0, addrs.Len()) - ) - for addr := range addrs { - if amountToConsume == 0 { - break - } - - prevFee, err := evm.CalculateDynamicFee(cost, baseFee) - if err != nil { - return nil, err - } - - newCost := cost + evm.EVMInputGas - newFee, err := evm.CalculateDynamicFee(newCost, baseFee) - if err != nil { - return nil, err - } - - additionalFee := newFee - prevFee - - balance, err := b.backend.Balance(ctx, addr) - if err != nil { - return nil, err - } - - // Since the asset is AVAX, we divide by the avaxConversionRate to - // convert back to the correct denomination of AVAX that can be - // exported. - avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() - - // If the balance for [addr] is insufficient to cover the additional - // cost of adding an input to the transaction, skip adding the input - // altogether. - if avaxBalance <= additionalFee { - continue - } - - // Update the cost for the next iteration - cost = newCost - - amountToConsume, err = math.Add64(amountToConsume, additionalFee) - if err != nil { - return nil, err - } - - nonce, err := b.backend.Nonce(ctx, addr) - if err != nil { - return nil, err - } - - inputAmount := math.Min(amountToConsume, avaxBalance) - inputs = append(inputs, evm.EVMInput{ - Address: addr, - Amount: inputAmount, - AssetID: avaxAssetID, - Nonce: nonce, - }) - amountToConsume -= inputAmount - } - - if amountToConsume > 0 { - return nil, errInsufficientFunds - } - - utils.Sort(inputs) - tx.Ins = inputs - return tx, nil -} - -func getSpendableAmount( - utxo *avax.UTXO, - addrs set.Set[ids.ShortID], - minIssuanceTime uint64, - avaxAssetID ids.ID, -) (uint64, []uint32, bool) { - if utxo.Asset.ID != avaxAssetID { - // Only AVAX can be imported - return 0, nil, false - } - - out, ok := utxo.Out.(*secp256k1fx.TransferOutput) - if !ok { - // Can't import an unknown transfer output type - return 0, nil, false - } - - inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) - return out.Amt, inputSigIndices, ok -} +// import ( +// "errors" +// "math/big" + +// stdcontext "context" + +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils" +// "github.com/ava-labs/avalanchego/utils/math" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// const avaxConversionRateInt = 1_000_000_000 + +// var ( +// _ Builder = (*builder)(nil) + +// errInsufficientFunds = errors.New("insufficient funds") + +// // avaxConversionRate is the conversion rate between the smallest +// // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest +// // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. +// // +// // This is only required for AVAX because the denomination of 1 AVAX is 9 +// // decimal places on the X and P chains, but is 18 decimal places within the +// // EVM. +// avaxConversionRate = big.NewInt(avaxConversionRateInt) +// ) + +// // Builder provides a convenient interface for building unsigned C-chain +// // transactions. +// type Builder interface { +// // GetBalance calculates the amount of AVAX that this builder has control +// // over. +// GetBalance( +// options ...common.Option, +// ) (*big.Int, error) + +// // GetImportableBalance calculates the amount of AVAX that this builder +// // could import from the provided chain. +// // +// // - [chainID] specifies the chain the funds are from. +// GetImportableBalance( +// chainID ids.ID, +// options ...common.Option, +// ) (uint64, error) + +// // NewImportTx creates an import transaction that attempts to consume all +// // the available UTXOs and import the funds to [to]. +// // +// // - [chainID] specifies the chain to be importing funds from. +// // - [to] specifies where to send the imported funds to. +// // - [baseFee] specifies the fee price willing to be paid by this tx. +// NewImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedImportTx, error) + +// // NewExportTx creates an export transaction that attempts to send all the +// // provided [outputs] to the requested [chainID]. +// // +// // - [chainID] specifies the chain to be exporting the funds to. +// // - [outputs] specifies the outputs to send to the [chainID]. +// // - [baseFee] specifies the fee price willing to be paid by this tx. +// NewExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedExportTx, error) +// } + +// // BuilderBackend specifies the required information needed to build unsigned +// // C-chain transactions. +// type BuilderBackend interface { +// Context + +// UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) +// Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) +// Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) +// } + +// type builder struct { +// avaxAddrs set.Set[ids.ShortID] +// ethAddrs set.Set[ethcommon.Address] +// backend BuilderBackend +// } + +// // NewBuilder returns a new transaction builder. +// // +// // - [avaxAddrs] is the set of addresses in the AVAX format that the builder +// // assumes can be used when signing the transactions in the future. +// // - [ethAddrs] is the set of addresses in the Eth format that the builder +// // assumes can be used when signing the transactions in the future. +// // - [backend] provides the required access to the chain's context and state +// // to build out the transactions. +// func NewBuilder( +// avaxAddrs set.Set[ids.ShortID], +// ethAddrs set.Set[ethcommon.Address], +// backend BuilderBackend, +// ) Builder { +// return &builder{ +// avaxAddrs: avaxAddrs, +// ethAddrs: ethAddrs, +// backend: backend, +// } +// } + +// func (b *builder) GetBalance( +// options ...common.Option, +// ) (*big.Int, error) { +// var ( +// ops = common.NewOptions(options) +// ctx = ops.Context() +// addrs = ops.EthAddresses(b.ethAddrs) +// totalBalance = new(big.Int) +// ) +// for addr := range addrs { +// balance, err := b.backend.Balance(ctx, addr) +// if err != nil { +// return nil, err +// } +// totalBalance.Add(totalBalance, balance) +// } + +// return totalBalance, nil +// } + +// func (b *builder) GetImportableBalance( +// chainID ids.ID, +// options ...common.Option, +// ) (uint64, error) { +// ops := common.NewOptions(options) +// utxos, err := b.backend.UTXOs(ops.Context(), chainID) +// if err != nil { +// return 0, err +// } + +// var ( +// addrs = ops.Addresses(b.avaxAddrs) +// minIssuanceTime = ops.MinIssuanceTime() +// avaxAssetID = b.backend.AVAXAssetID() +// balance uint64 +// ) +// for _, utxo := range utxos { +// amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) +// if !ok { +// continue +// } + +// newBalance, err := math.Add64(balance, amount) +// if err != nil { +// return 0, err +// } +// balance = newBalance +// } + +// return balance, nil +// } + +// func (b *builder) NewImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedImportTx, error) { +// ops := common.NewOptions(options) +// utxos, err := b.backend.UTXOs(ops.Context(), chainID) +// if err != nil { +// return nil, err +// } + +// var ( +// addrs = ops.Addresses(b.avaxAddrs) +// minIssuanceTime = ops.MinIssuanceTime() +// avaxAssetID = b.backend.AVAXAssetID() + +// importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) +// importedAmount uint64 +// ) +// for _, utxo := range utxos { +// amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) +// if !ok { +// continue +// } + +// importedInputs = append(importedInputs, &avax.TransferableInput{ +// UTXOID: utxo.UTXOID, +// Asset: utxo.Asset, +// In: &secp256k1fx.TransferInput{ +// Amt: amount, +// Input: secp256k1fx.Input{ +// SigIndices: inputSigIndices, +// }, +// }, +// }) + +// newImportedAmount, err := math.Add64(importedAmount, amount) +// if err != nil { +// return nil, err +// } +// importedAmount = newImportedAmount +// } + +// utils.Sort(importedInputs) +// tx := &evm.UnsignedImportTx{ +// NetworkID: b.backend.NetworkID(), +// BlockchainID: b.backend.BlockchainID(), +// SourceChain: chainID, +// ImportedInputs: importedInputs, +// } + +// // We must initialize the bytes of the tx to calculate the initial cost +// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} +// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { +// return nil, err +// } + +// gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) +// if err != nil { +// return nil, err +// } +// gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas + +// txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) +// if err != nil { +// return nil, err +// } + +// if importedAmount <= txFee { +// return nil, errInsufficientFunds +// } + +// tx.Outs = []evm.EVMOutput{{ +// Address: to, +// Amount: importedAmount - txFee, +// AssetID: avaxAssetID, +// }} +// return tx, nil +// } + +// func (b *builder) NewExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedExportTx, error) { +// var ( +// avaxAssetID = b.backend.AVAXAssetID() +// exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) +// exportedAmount uint64 +// ) +// for i, output := range outputs { +// exportedOutputs[i] = &avax.TransferableOutput{ +// Asset: avax.Asset{ID: avaxAssetID}, +// Out: output, +// } + +// newExportedAmount, err := math.Add64(exportedAmount, output.Amt) +// if err != nil { +// return nil, err +// } +// exportedAmount = newExportedAmount +// } + +// avax.SortTransferableOutputs(exportedOutputs, evm.Codec) +// tx := &evm.UnsignedExportTx{ +// NetworkID: b.backend.NetworkID(), +// BlockchainID: b.backend.BlockchainID(), +// DestinationChain: chainID, +// ExportedOutputs: exportedOutputs, +// } + +// // We must initialize the bytes of the tx to calculate the initial cost +// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} +// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { +// return nil, err +// } + +// cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) +// if err != nil { +// return nil, err +// } + +// initialFee, err := evm.CalculateDynamicFee(cost, baseFee) +// if err != nil { +// return nil, err +// } + +// amountToConsume, err := math.Add64(exportedAmount, initialFee) +// if err != nil { +// return nil, err +// } + +// var ( +// ops = common.NewOptions(options) +// ctx = ops.Context() +// addrs = ops.EthAddresses(b.ethAddrs) +// inputs = make([]evm.EVMInput, 0, addrs.Len()) +// ) +// for addr := range addrs { +// if amountToConsume == 0 { +// break +// } + +// prevFee, err := evm.CalculateDynamicFee(cost, baseFee) +// if err != nil { +// return nil, err +// } + +// newCost := cost + evm.EVMInputGas +// newFee, err := evm.CalculateDynamicFee(newCost, baseFee) +// if err != nil { +// return nil, err +// } + +// additionalFee := newFee - prevFee + +// balance, err := b.backend.Balance(ctx, addr) +// if err != nil { +// return nil, err +// } + +// // Since the asset is AVAX, we divide by the avaxConversionRate to +// // convert back to the correct denomination of AVAX that can be +// // exported. +// avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() + +// // If the balance for [addr] is insufficient to cover the additional +// // cost of adding an input to the transaction, skip adding the input +// // altogether. +// if avaxBalance <= additionalFee { +// continue +// } + +// // Update the cost for the next iteration +// cost = newCost + +// amountToConsume, err = math.Add64(amountToConsume, additionalFee) +// if err != nil { +// return nil, err +// } + +// nonce, err := b.backend.Nonce(ctx, addr) +// if err != nil { +// return nil, err +// } + +// inputAmount := math.Min(amountToConsume, avaxBalance) +// inputs = append(inputs, evm.EVMInput{ +// Address: addr, +// Amount: inputAmount, +// AssetID: avaxAssetID, +// Nonce: nonce, +// }) +// amountToConsume -= inputAmount +// } + +// if amountToConsume > 0 { +// return nil, errInsufficientFunds +// } + +// utils.Sort(inputs) +// tx.Ins = inputs +// return tx, nil +// } + +// func getSpendableAmount( +// utxo *avax.UTXO, +// addrs set.Set[ids.ShortID], +// minIssuanceTime uint64, +// avaxAssetID ids.ID, +// ) (uint64, []uint32, bool) { +// if utxo.Asset.ID != avaxAssetID { +// // Only AVAX can be imported +// return 0, nil, false +// } + +// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) +// if !ok { +// // Can't import an unknown transfer output type +// return 0, nil, false +// } + +// inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) +// return out.Amt, inputSigIndices, ok +// } diff --git a/wallet/chain/c/builder_with_options.go b/wallet/chain/c/builder_with_options.go index 8416dddf9928..9b7ab8399484 100644 --- a/wallet/chain/c/builder_with_options.go +++ b/wallet/chain/c/builder_with_options.go @@ -3,81 +3,81 @@ package c -import ( - "math/big" +// import ( +// "math/big" - "github.com/ava-labs/coreth/plugin/evm" +// "github.com/ava-labs/coreth/plugin/evm" - ethcommon "github.com/ethereum/go-ethereum/common" +// ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) -var _ Builder = (*builderWithOptions)(nil) +// var _ Builder = (*builderWithOptions)(nil) -type builderWithOptions struct { - Builder - options []common.Option -} +// type builderWithOptions struct { +// Builder +// options []common.Option +// } -// NewBuilderWithOptions returns a new transaction builder that will use the -// given options by default. -// -// - [builder] is the builder that will be called to perform the underlying -// operations. -// - [options] will be provided to the builder in addition to the options -// provided in the method calls. -func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { - return &builderWithOptions{ - Builder: builder, - options: options, - } -} +// // NewBuilderWithOptions returns a new transaction builder that will use the +// // given options by default. +// // +// // - [builder] is the builder that will be called to perform the underlying +// // operations. +// // - [options] will be provided to the builder in addition to the options +// // provided in the method calls. +// func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { +// return &builderWithOptions{ +// Builder: builder, +// options: options, +// } +// } -func (b *builderWithOptions) GetBalance( - options ...common.Option, -) (*big.Int, error) { - return b.Builder.GetBalance( - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) GetBalance( +// options ...common.Option, +// ) (*big.Int, error) { +// return b.Builder.GetBalance( +// common.UnionOptions(b.options, options)..., +// ) +// } -func (b *builderWithOptions) GetImportableBalance( - chainID ids.ID, - options ...common.Option, -) (uint64, error) { - return b.Builder.GetImportableBalance( - chainID, - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) GetImportableBalance( +// chainID ids.ID, +// options ...common.Option, +// ) (uint64, error) { +// return b.Builder.GetImportableBalance( +// chainID, +// common.UnionOptions(b.options, options)..., +// ) +// } -func (b *builderWithOptions) NewImportTx( - chainID ids.ID, - to ethcommon.Address, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedImportTx, error) { - return b.Builder.NewImportTx( - chainID, - to, - baseFee, - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) NewImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedImportTx, error) { +// return b.Builder.NewImportTx( +// chainID, +// to, +// baseFee, +// common.UnionOptions(b.options, options)..., +// ) +// } -func (b *builderWithOptions) NewExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedExportTx, error) { - return b.Builder.NewExportTx( - chainID, - outputs, - baseFee, - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) NewExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedExportTx, error) { +// return b.Builder.NewExportTx( +// chainID, +// outputs, +// baseFee, +// common.UnionOptions(b.options, options)..., +// ) +// } diff --git a/wallet/chain/c/context.go b/wallet/chain/c/context.go index d506b42f81fa..1c01d8fb55c8 100644 --- a/wallet/chain/c/context.go +++ b/wallet/chain/c/context.go @@ -3,81 +3,81 @@ package c -import ( - stdcontext "context" +// import ( +// stdcontext "context" - "github.com/ava-labs/avalanchego/api/info" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/avm" -) +// "github.com/ava-labs/avalanchego/api/info" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/avm" +// ) -var _ Context = (*context)(nil) +// var _ Context = (*context)(nil) -type Context interface { - NetworkID() uint32 - BlockchainID() ids.ID - AVAXAssetID() ids.ID -} +// type Context interface { +// NetworkID() uint32 +// BlockchainID() ids.ID +// AVAXAssetID() ids.ID +// } -type context struct { - networkID uint32 - blockchainID ids.ID - avaxAssetID ids.ID -} +// type context struct { +// networkID uint32 +// blockchainID ids.ID +// avaxAssetID ids.ID +// } -func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { - infoClient := info.NewClient(uri) - xChainClient := avm.NewClient(uri, "X") - return NewContextFromClients(ctx, infoClient, xChainClient) -} +// func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { +// infoClient := info.NewClient(uri) +// xChainClient := avm.NewClient(uri, "X") +// return NewContextFromClients(ctx, infoClient, xChainClient) +// } -func NewContextFromClients( - ctx stdcontext.Context, - infoClient info.Client, - xChainClient avm.Client, -) (Context, error) { - networkID, err := infoClient.GetNetworkID(ctx) - if err != nil { - return nil, err - } +// func NewContextFromClients( +// ctx stdcontext.Context, +// infoClient info.Client, +// xChainClient avm.Client, +// ) (Context, error) { +// networkID, err := infoClient.GetNetworkID(ctx) +// if err != nil { +// return nil, err +// } - chainID, err := infoClient.GetBlockchainID(ctx, "C") - if err != nil { - return nil, err - } +// chainID, err := infoClient.GetBlockchainID(ctx, "C") +// if err != nil { +// return nil, err +// } - asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") - if err != nil { - return nil, err - } +// asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") +// if err != nil { +// return nil, err +// } - return NewContext( - networkID, - chainID, - asset.AssetID, - ), nil -} +// return NewContext( +// networkID, +// chainID, +// asset.AssetID, +// ), nil +// } -func NewContext( - networkID uint32, - blockchainID ids.ID, - avaxAssetID ids.ID, -) Context { - return &context{ - networkID: networkID, - blockchainID: blockchainID, - avaxAssetID: avaxAssetID, - } -} +// func NewContext( +// networkID uint32, +// blockchainID ids.ID, +// avaxAssetID ids.ID, +// ) Context { +// return &context{ +// networkID: networkID, +// blockchainID: blockchainID, +// avaxAssetID: avaxAssetID, +// } +// } -func (c *context) NetworkID() uint32 { - return c.networkID -} +// func (c *context) NetworkID() uint32 { +// return c.networkID +// } -func (c *context) BlockchainID() ids.ID { - return c.blockchainID -} +// func (c *context) BlockchainID() ids.ID { +// return c.blockchainID +// } -func (c *context) AVAXAssetID() ids.ID { - return c.avaxAssetID -} +// func (c *context) AVAXAssetID() ids.ID { +// return c.avaxAssetID +// } diff --git a/wallet/chain/c/signer.go b/wallet/chain/c/signer.go index 4fd85ed3b532..4bedc378234b 100644 --- a/wallet/chain/c/signer.go +++ b/wallet/chain/c/signer.go @@ -3,221 +3,221 @@ package c -import ( - "errors" - "fmt" - - stdcontext "context" - - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/crypto/keychain" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/hashing" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/components/verify" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" -) - -const version = 0 - -var ( - _ Signer = (*txSigner)(nil) - - errUnknownInputType = errors.New("unknown input type") - errUnknownCredentialType = errors.New("unknown credential type") - errUnknownOutputType = errors.New("unknown output type") - errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") - - emptySig [secp256k1.SignatureLen]byte -) - -type Signer interface { - SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) - SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error -} - -type EthKeychain interface { - // The returned Signer can provide a signature for [addr] - GetEth(addr ethcommon.Address) (keychain.Signer, bool) - // Returns the set of addresses for which the accessor keeps an associated - // signer - EthAddresses() set.Set[ethcommon.Address] -} - -type SignerBackend interface { - GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) -} - -type txSigner struct { - avaxKC keychain.Keychain - ethKC EthKeychain - backend SignerBackend -} - -func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { - return &txSigner{ - avaxKC: avaxKC, - ethKC: ethKC, - backend: backend, - } -} - -func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { - tx := &evm.Tx{UnsignedAtomicTx: utx} - return tx, s.SignAtomic(ctx, tx) -} - -func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { - switch utx := tx.UnsignedAtomicTx.(type) { - case *evm.UnsignedImportTx: - signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) - if err != nil { - return err - } - return sign(tx, true, signers) - case *evm.UnsignedExportTx: - signers := s.getExportSigners(utx.Ins) - return sign(tx, true, signers) - default: - return fmt.Errorf("%w: %T", errUnknownTxType, tx) - } -} - -func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { - txSigners := make([][]keychain.Signer, len(ins)) - for credIndex, transferInput := range ins { - input, ok := transferInput.In.(*secp256k1fx.TransferInput) - if !ok { - return nil, errUnknownInputType - } - - inputSigners := make([]keychain.Signer, len(input.SigIndices)) - txSigners[credIndex] = inputSigners - - utxoID := transferInput.InputID() - utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) - if err == database.ErrNotFound { - // If we don't have access to the UTXO, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - if err != nil { - return nil, err - } - - out, ok := utxo.Out.(*secp256k1fx.TransferOutput) - if !ok { - return nil, errUnknownOutputType - } - - for sigIndex, addrIndex := range input.SigIndices { - if addrIndex >= uint32(len(out.Addrs)) { - return nil, errInvalidUTXOSigIndex - } - - addr := out.Addrs[addrIndex] - key, ok := s.avaxKC.Get(addr) - if !ok { - // If we don't have access to the key, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - inputSigners[sigIndex] = key - } - } - return txSigners, nil -} - -func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { - txSigners := make([][]keychain.Signer, len(ins)) - for credIndex, input := range ins { - inputSigners := make([]keychain.Signer, 1) - txSigners[credIndex] = inputSigners - - key, ok := s.ethKC.GetEth(input.Address) - if !ok { - // If we don't have access to the key, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - inputSigners[0] = key - } - return txSigners -} - -// TODO: remove [signHash] after the ledger supports signing all transactions. -func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { - unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) - if err != nil { - return fmt.Errorf("couldn't marshal unsigned tx: %w", err) - } - unsignedHash := hashing.ComputeHash256(unsignedBytes) - - if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { - tx.Creds = make([]verify.Verifiable, expectedLen) - } - - sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) - for credIndex, inputSigners := range txSigners { - credIntf := tx.Creds[credIndex] - if credIntf == nil { - credIntf = &secp256k1fx.Credential{} - tx.Creds[credIndex] = credIntf - } - - cred, ok := credIntf.(*secp256k1fx.Credential) - if !ok { - return errUnknownCredentialType - } - if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { - cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) - } - - for sigIndex, signer := range inputSigners { - if signer == nil { - // If we don't have access to the key, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - addr := signer.Address() - if sig := cred.Sigs[sigIndex]; sig != emptySig { - // If this signature has already been populated, we can just - // copy the needed signature for the future. - sigCache[addr] = sig - continue - } - - if sig, exists := sigCache[addr]; exists { - // If this key has already produced a signature, we can just - // copy the previous signature. - cred.Sigs[sigIndex] = sig - continue - } - - var sig []byte - if signHash { - sig, err = signer.SignHash(unsignedHash) - } else { - sig, err = signer.Sign(unsignedBytes) - } - if err != nil { - return fmt.Errorf("problem signing tx: %w", err) - } - copy(cred.Sigs[sigIndex][:], sig) - sigCache[addr] = cred.Sigs[sigIndex] - } - } - - signedBytes, err := evm.Codec.Marshal(version, tx) - if err != nil { - return fmt.Errorf("couldn't marshal tx: %w", err) - } - tx.Initialize(unsignedBytes, signedBytes) - return nil -} +// import ( +// "errors" +// "fmt" + +// stdcontext "context" + +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/database" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils/crypto/keychain" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/hashing" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/components/verify" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// ) + +// const version = 0 + +// var ( +// _ Signer = (*txSigner)(nil) + +// errUnknownInputType = errors.New("unknown input type") +// errUnknownCredentialType = errors.New("unknown credential type") +// errUnknownOutputType = errors.New("unknown output type") +// errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") + +// emptySig [secp256k1.SignatureLen]byte +// ) + +// type Signer interface { +// SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) +// SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error +// } + +// type EthKeychain interface { +// // The returned Signer can provide a signature for [addr] +// GetEth(addr ethcommon.Address) (keychain.Signer, bool) +// // Returns the set of addresses for which the accessor keeps an associated +// // signer +// EthAddresses() set.Set[ethcommon.Address] +// } + +// type SignerBackend interface { +// GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) +// } + +// type txSigner struct { +// avaxKC keychain.Keychain +// ethKC EthKeychain +// backend SignerBackend +// } + +// func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { +// return &txSigner{ +// avaxKC: avaxKC, +// ethKC: ethKC, +// backend: backend, +// } +// } + +// func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { +// tx := &evm.Tx{UnsignedAtomicTx: utx} +// return tx, s.SignAtomic(ctx, tx) +// } + +// func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { +// switch utx := tx.UnsignedAtomicTx.(type) { +// case *evm.UnsignedImportTx: +// signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) +// if err != nil { +// return err +// } +// return sign(tx, true, signers) +// case *evm.UnsignedExportTx: +// signers := s.getExportSigners(utx.Ins) +// return sign(tx, true, signers) +// default: +// return fmt.Errorf("%w: %T", errUnknownTxType, tx) +// } +// } + +// func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { +// txSigners := make([][]keychain.Signer, len(ins)) +// for credIndex, transferInput := range ins { +// input, ok := transferInput.In.(*secp256k1fx.TransferInput) +// if !ok { +// return nil, errUnknownInputType +// } + +// inputSigners := make([]keychain.Signer, len(input.SigIndices)) +// txSigners[credIndex] = inputSigners + +// utxoID := transferInput.InputID() +// utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) +// if err == database.ErrNotFound { +// // If we don't have access to the UTXO, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// if err != nil { +// return nil, err +// } + +// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) +// if !ok { +// return nil, errUnknownOutputType +// } + +// for sigIndex, addrIndex := range input.SigIndices { +// if addrIndex >= uint32(len(out.Addrs)) { +// return nil, errInvalidUTXOSigIndex +// } + +// addr := out.Addrs[addrIndex] +// key, ok := s.avaxKC.Get(addr) +// if !ok { +// // If we don't have access to the key, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// inputSigners[sigIndex] = key +// } +// } +// return txSigners, nil +// } + +// func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { +// txSigners := make([][]keychain.Signer, len(ins)) +// for credIndex, input := range ins { +// inputSigners := make([]keychain.Signer, 1) +// txSigners[credIndex] = inputSigners + +// key, ok := s.ethKC.GetEth(input.Address) +// if !ok { +// // If we don't have access to the key, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// inputSigners[0] = key +// } +// return txSigners +// } + +// // TODO: remove [signHash] after the ledger supports signing all transactions. +// func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { +// unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) +// if err != nil { +// return fmt.Errorf("couldn't marshal unsigned tx: %w", err) +// } +// unsignedHash := hashing.ComputeHash256(unsignedBytes) + +// if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { +// tx.Creds = make([]verify.Verifiable, expectedLen) +// } + +// sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) +// for credIndex, inputSigners := range txSigners { +// credIntf := tx.Creds[credIndex] +// if credIntf == nil { +// credIntf = &secp256k1fx.Credential{} +// tx.Creds[credIndex] = credIntf +// } + +// cred, ok := credIntf.(*secp256k1fx.Credential) +// if !ok { +// return errUnknownCredentialType +// } +// if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { +// cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) +// } + +// for sigIndex, signer := range inputSigners { +// if signer == nil { +// // If we don't have access to the key, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// addr := signer.Address() +// if sig := cred.Sigs[sigIndex]; sig != emptySig { +// // If this signature has already been populated, we can just +// // copy the needed signature for the future. +// sigCache[addr] = sig +// continue +// } + +// if sig, exists := sigCache[addr]; exists { +// // If this key has already produced a signature, we can just +// // copy the previous signature. +// cred.Sigs[sigIndex] = sig +// continue +// } + +// var sig []byte +// if signHash { +// sig, err = signer.SignHash(unsignedHash) +// } else { +// sig, err = signer.Sign(unsignedBytes) +// } +// if err != nil { +// return fmt.Errorf("problem signing tx: %w", err) +// } +// copy(cred.Sigs[sigIndex][:], sig) +// sigCache[addr] = cred.Sigs[sigIndex] +// } +// } + +// signedBytes, err := evm.Codec.Marshal(version, tx) +// if err != nil { +// return fmt.Errorf("couldn't marshal tx: %w", err) +// } +// tx.Initialize(unsignedBytes, signedBytes) +// return nil +// } diff --git a/wallet/chain/c/wallet.go b/wallet/chain/c/wallet.go index fb1a83d53dad..ebee50a9a958 100644 --- a/wallet/chain/c/wallet.go +++ b/wallet/chain/c/wallet.go @@ -3,204 +3,204 @@ package c -import ( - "errors" - "math/big" - "time" - - "github.com/ava-labs/coreth/ethclient" - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var ( - _ Wallet = (*wallet)(nil) - - errNotCommitted = errors.New("not committed") -) - -type Wallet interface { - Context - - // Builder returns the builder that will be used to create the transactions. - Builder() Builder - - // Signer returns the signer that will be used to sign the transactions. - Signer() Signer - - // IssueImportTx creates, signs, and issues an import transaction that - // attempts to consume all the available UTXOs and import the funds to [to]. - // - // - [chainID] specifies the chain to be importing funds from. - // - [to] specifies where to send the imported funds to. - IssueImportTx( - chainID ids.ID, - to ethcommon.Address, - options ...common.Option, - ) (*evm.Tx, error) - - // IssueExportTx creates, signs, and issues an export transaction that - // attempts to send all the provided [outputs] to the requested [chainID]. - // - // - [chainID] specifies the chain to be exporting the funds to. - // - [outputs] specifies the outputs to send to the [chainID]. - IssueExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - options ...common.Option, - ) (*evm.Tx, error) - - // IssueUnsignedTx signs and issues the unsigned tx. - IssueUnsignedAtomicTx( - utx evm.UnsignedAtomicTx, - options ...common.Option, - ) (*evm.Tx, error) - - // IssueAtomicTx issues the signed tx. - IssueAtomicTx( - tx *evm.Tx, - options ...common.Option, - ) error -} - -func NewWallet( - builder Builder, - signer Signer, - avaxClient evm.Client, - ethClient ethclient.Client, - backend Backend, -) Wallet { - return &wallet{ - Backend: backend, - builder: builder, - signer: signer, - avaxClient: avaxClient, - ethClient: ethClient, - } -} - -type wallet struct { - Backend - builder Builder - signer Signer - avaxClient evm.Client - ethClient ethclient.Client -} - -func (w *wallet) Builder() Builder { - return w.builder -} - -func (w *wallet) Signer() Signer { - return w.signer -} - -func (w *wallet) IssueImportTx( - chainID ids.ID, - to ethcommon.Address, - options ...common.Option, -) (*evm.Tx, error) { - baseFee, err := w.baseFee(options) - if err != nil { - return nil, err - } - - utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) - if err != nil { - return nil, err - } - return w.IssueUnsignedAtomicTx(utx, options...) -} - -func (w *wallet) IssueExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - options ...common.Option, -) (*evm.Tx, error) { - baseFee, err := w.baseFee(options) - if err != nil { - return nil, err - } - - utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) - if err != nil { - return nil, err - } - return w.IssueUnsignedAtomicTx(utx, options...) -} - -func (w *wallet) IssueUnsignedAtomicTx( - utx evm.UnsignedAtomicTx, - options ...common.Option, -) (*evm.Tx, error) { - ops := common.NewOptions(options) - ctx := ops.Context() - tx, err := w.signer.SignUnsignedAtomic(ctx, utx) - if err != nil { - return nil, err - } - - return tx, w.IssueAtomicTx(tx, options...) -} - -func (w *wallet) IssueAtomicTx( - tx *evm.Tx, - options ...common.Option, -) error { - ops := common.NewOptions(options) - ctx := ops.Context() - txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) - if err != nil { - return err - } - - if f := ops.PostIssuanceFunc(); f != nil { - f(txID) - } - - if ops.AssumeDecided() { - return w.Backend.AcceptAtomicTx(ctx, tx) - } - - pollFrequency := ops.PollFrequency() - ticker := time.NewTicker(pollFrequency) - defer ticker.Stop() - - for { - status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) - if err != nil { - return err - } - - switch status { - case evm.Accepted: - return w.Backend.AcceptAtomicTx(ctx, tx) - case evm.Dropped, evm.Unknown: - return errNotCommitted - } - - // The tx is Processing. - - select { - case <-ticker.C: - case <-ctx.Done(): - return ctx.Err() - } - } -} - -func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { - ops := common.NewOptions(options) - baseFee := ops.BaseFee(nil) - if baseFee != nil { - return baseFee, nil - } - - ctx := ops.Context() - return w.ethClient.EstimateBaseFee(ctx) -} +// import ( +// "errors" +// "math/big" +// "time" + +// "github.com/ava-labs/coreth/ethclient" +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var ( +// _ Wallet = (*wallet)(nil) + +// errNotCommitted = errors.New("not committed") +// ) + +// type Wallet interface { +// Context + +// // Builder returns the builder that will be used to create the transactions. +// Builder() Builder + +// // Signer returns the signer that will be used to sign the transactions. +// Signer() Signer + +// // IssueImportTx creates, signs, and issues an import transaction that +// // attempts to consume all the available UTXOs and import the funds to [to]. +// // +// // - [chainID] specifies the chain to be importing funds from. +// // - [to] specifies where to send the imported funds to. +// IssueImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// options ...common.Option, +// ) (*evm.Tx, error) + +// // IssueExportTx creates, signs, and issues an export transaction that +// // attempts to send all the provided [outputs] to the requested [chainID]. +// // +// // - [chainID] specifies the chain to be exporting the funds to. +// // - [outputs] specifies the outputs to send to the [chainID]. +// IssueExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// options ...common.Option, +// ) (*evm.Tx, error) + +// // IssueUnsignedTx signs and issues the unsigned tx. +// IssueUnsignedAtomicTx( +// utx evm.UnsignedAtomicTx, +// options ...common.Option, +// ) (*evm.Tx, error) + +// // IssueAtomicTx issues the signed tx. +// IssueAtomicTx( +// tx *evm.Tx, +// options ...common.Option, +// ) error +// } + +// func NewWallet( +// builder Builder, +// signer Signer, +// avaxClient evm.Client, +// ethClient ethclient.Client, +// backend Backend, +// ) Wallet { +// return &wallet{ +// Backend: backend, +// builder: builder, +// signer: signer, +// avaxClient: avaxClient, +// ethClient: ethClient, +// } +// } + +// type wallet struct { +// Backend +// builder Builder +// signer Signer +// avaxClient evm.Client +// ethClient ethclient.Client +// } + +// func (w *wallet) Builder() Builder { +// return w.builder +// } + +// func (w *wallet) Signer() Signer { +// return w.signer +// } + +// func (w *wallet) IssueImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// options ...common.Option, +// ) (*evm.Tx, error) { +// baseFee, err := w.baseFee(options) +// if err != nil { +// return nil, err +// } + +// utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) +// if err != nil { +// return nil, err +// } +// return w.IssueUnsignedAtomicTx(utx, options...) +// } + +// func (w *wallet) IssueExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// options ...common.Option, +// ) (*evm.Tx, error) { +// baseFee, err := w.baseFee(options) +// if err != nil { +// return nil, err +// } + +// utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) +// if err != nil { +// return nil, err +// } +// return w.IssueUnsignedAtomicTx(utx, options...) +// } + +// func (w *wallet) IssueUnsignedAtomicTx( +// utx evm.UnsignedAtomicTx, +// options ...common.Option, +// ) (*evm.Tx, error) { +// ops := common.NewOptions(options) +// ctx := ops.Context() +// tx, err := w.signer.SignUnsignedAtomic(ctx, utx) +// if err != nil { +// return nil, err +// } + +// return tx, w.IssueAtomicTx(tx, options...) +// } + +// func (w *wallet) IssueAtomicTx( +// tx *evm.Tx, +// options ...common.Option, +// ) error { +// ops := common.NewOptions(options) +// ctx := ops.Context() +// txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) +// if err != nil { +// return err +// } + +// if f := ops.PostIssuanceFunc(); f != nil { +// f(txID) +// } + +// if ops.AssumeDecided() { +// return w.Backend.AcceptAtomicTx(ctx, tx) +// } + +// pollFrequency := ops.PollFrequency() +// ticker := time.NewTicker(pollFrequency) +// defer ticker.Stop() + +// for { +// status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) +// if err != nil { +// return err +// } + +// switch status { +// case evm.Accepted: +// return w.Backend.AcceptAtomicTx(ctx, tx) +// case evm.Dropped, evm.Unknown: +// return errNotCommitted +// } + +// // The tx is Processing. + +// select { +// case <-ticker.C: +// case <-ctx.Done(): +// return ctx.Err() +// } +// } +// } + +// func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { +// ops := common.NewOptions(options) +// baseFee := ops.BaseFee(nil) +// if baseFee != nil { +// return baseFee, nil +// } + +// ctx := ops.Context() +// return w.ethClient.EstimateBaseFee(ctx) +// } diff --git a/wallet/chain/c/wallet_with_options.go b/wallet/chain/c/wallet_with_options.go index 7d6193683d49..fd69a6d4fd02 100644 --- a/wallet/chain/c/wallet_with_options.go +++ b/wallet/chain/c/wallet_with_options.go @@ -3,80 +3,80 @@ package c -import ( - "github.com/ava-labs/coreth/plugin/evm" +// import ( +// "github.com/ava-labs/coreth/plugin/evm" - ethcommon "github.com/ethereum/go-ethereum/common" +// ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) -var _ Wallet = (*walletWithOptions)(nil) +// var _ Wallet = (*walletWithOptions)(nil) -func NewWalletWithOptions( - wallet Wallet, - options ...common.Option, -) Wallet { - return &walletWithOptions{ - Wallet: wallet, - options: options, - } -} +// func NewWalletWithOptions( +// wallet Wallet, +// options ...common.Option, +// ) Wallet { +// return &walletWithOptions{ +// Wallet: wallet, +// options: options, +// } +// } -type walletWithOptions struct { - Wallet - options []common.Option -} +// type walletWithOptions struct { +// Wallet +// options []common.Option +// } -func (w *walletWithOptions) Builder() Builder { - return NewBuilderWithOptions( - w.Wallet.Builder(), - w.options..., - ) -} +// func (w *walletWithOptions) Builder() Builder { +// return NewBuilderWithOptions( +// w.Wallet.Builder(), +// w.options..., +// ) +// } -func (w *walletWithOptions) IssueImportTx( - chainID ids.ID, - to ethcommon.Address, - options ...common.Option, -) (*evm.Tx, error) { - return w.Wallet.IssueImportTx( - chainID, - to, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// options ...common.Option, +// ) (*evm.Tx, error) { +// return w.Wallet.IssueImportTx( +// chainID, +// to, +// common.UnionOptions(w.options, options)..., +// ) +// } -func (w *walletWithOptions) IssueExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - options ...common.Option, -) (*evm.Tx, error) { - return w.Wallet.IssueExportTx( - chainID, - outputs, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// options ...common.Option, +// ) (*evm.Tx, error) { +// return w.Wallet.IssueExportTx( +// chainID, +// outputs, +// common.UnionOptions(w.options, options)..., +// ) +// } -func (w *walletWithOptions) IssueUnsignedAtomicTx( - utx evm.UnsignedAtomicTx, - options ...common.Option, -) (*evm.Tx, error) { - return w.Wallet.IssueUnsignedAtomicTx( - utx, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueUnsignedAtomicTx( +// utx evm.UnsignedAtomicTx, +// options ...common.Option, +// ) (*evm.Tx, error) { +// return w.Wallet.IssueUnsignedAtomicTx( +// utx, +// common.UnionOptions(w.options, options)..., +// ) +// } -func (w *walletWithOptions) IssueAtomicTx( - tx *evm.Tx, - options ...common.Option, -) error { - return w.Wallet.IssueAtomicTx( - tx, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueAtomicTx( +// tx *evm.Tx, +// options ...common.Option, +// ) error { +// return w.Wallet.IssueAtomicTx( +// tx, +// common.UnionOptions(w.options, options)..., +// ) +// } diff --git a/wallet/subnet/primary/api.go b/wallet/subnet/primary/api.go index 3ac72c217884..3260c05a0a1b 100644 --- a/wallet/subnet/primary/api.go +++ b/wallet/subnet/primary/api.go @@ -5,12 +5,6 @@ package primary import ( "context" - "fmt" - - "github.com/ava-labs/coreth/ethclient" - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ethereum/go-ethereum/common" "github.com/ava-labs/avalanchego/api/info" "github.com/ava-labs/avalanchego/codec" @@ -22,7 +16,6 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm" "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" ) @@ -59,9 +52,9 @@ type AVAXState struct { PCTX p.Context XClient avm.Client XCTX x.Context - CClient evm.Client - CCTX c.Context - UTXOs UTXOs + // CClient evm.Client + // CCTX c.Context + UTXOs UTXOs } func FetchState( @@ -75,7 +68,7 @@ func FetchState( infoClient := info.NewClient(uri) pClient := platformvm.NewClient(uri) xClient := avm.NewClient(uri, "X") - cClient := evm.NewCChainClient(uri) + // cClient := evm.NewCChainClient(uri) pCTX, err := p.NewContextFromClients(ctx, infoClient, xClient) if err != nil { @@ -87,10 +80,10 @@ func FetchState( return nil, err } - cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) - if err != nil { - return nil, err - } + // cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) + // if err != nil { + // return nil, err + // } utxos := NewUTXOs() addrList := addrs.List() @@ -109,11 +102,11 @@ func FetchState( client: xClient, codec: x.Parser.Codec(), }, - { - id: cCTX.BlockchainID(), - client: cClient, - codec: evm.Codec, - }, + // { + // id: cCTX.BlockchainID(), + // client: cClient, + // codec: evm.Codec, + // }, } for _, destinationChain := range chains { for _, sourceChain := range chains { @@ -136,52 +129,52 @@ func FetchState( PCTX: pCTX, XClient: xClient, XCTX: xCTX, - CClient: cClient, - CCTX: cCTX, - UTXOs: utxos, + // CClient: cClient, + // CCTX: cCTX, + UTXOs: utxos, }, nil } -type EthState struct { - Client ethclient.Client - Accounts map[common.Address]*c.Account -} - -func FetchEthState( - ctx context.Context, - uri string, - addrs set.Set[common.Address], -) (*EthState, error) { - path := fmt.Sprintf( - "%s/ext/%s/C/rpc", - uri, - constants.ChainAliasPrefix, - ) - client, err := ethclient.Dial(path) - if err != nil { - return nil, err - } - - accounts := make(map[common.Address]*c.Account, addrs.Len()) - for addr := range addrs { - balance, err := client.BalanceAt(ctx, addr, nil) - if err != nil { - return nil, err - } - nonce, err := client.NonceAt(ctx, addr, nil) - if err != nil { - return nil, err - } - accounts[addr] = &c.Account{ - Balance: balance, - Nonce: nonce, - } - } - return &EthState{ - Client: client, - Accounts: accounts, - }, nil -} +// type EthState struct { +// Client ethclient.Client +// Accounts map[common.Address]*c.Account +// } + +// func FetchEthState( +// ctx context.Context, +// uri string, +// addrs set.Set[common.Address], +// ) (*EthState, error) { +// path := fmt.Sprintf( +// "%s/ext/%s/C/rpc", +// uri, +// constants.ChainAliasPrefix, +// ) +// client, err := ethclient.Dial(path) +// if err != nil { +// return nil, err +// } + +// accounts := make(map[common.Address]*c.Account, addrs.Len()) +// for addr := range addrs { +// balance, err := client.BalanceAt(ctx, addr, nil) +// if err != nil { +// return nil, err +// } +// nonce, err := client.NonceAt(ctx, addr, nil) +// if err != nil { +// return nil, err +// } +// accounts[addr] = &c.Account{ +// Balance: balance, +// Nonce: nonce, +// } +// } +// return &EthState{ +// Client: client, +// Accounts: accounts, +// }, nil +// } // AddAllUTXOs fetches all the UTXOs referenced by [addresses] that were sent // from [sourceChainID] to [destinationChainID] from the [client]. It then uses diff --git a/wallet/subnet/primary/example_test.go b/wallet/subnet/primary/example_test.go index 483c049d4ac0..4a73e8c070b2 100644 --- a/wallet/subnet/primary/example_test.go +++ b/wallet/subnet/primary/example_test.go @@ -30,7 +30,7 @@ func ExampleWallet() { wallet, err := MakeWallet(ctx, &WalletConfig{ URI: LocalAPIURI, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet with: %s\n", err) diff --git a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go index d5e8ce422307..21c081d2982b 100644 --- a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go @@ -46,9 +46,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/add-primary-validator/main.go b/wallet/subnet/primary/examples/add-primary-validator/main.go index a56dae23db3a..13c28f995f63 100644 --- a/wallet/subnet/primary/examples/add-primary-validator/main.go +++ b/wallet/subnet/primary/examples/add-primary-validator/main.go @@ -45,7 +45,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/c-chain-export/main.go b/wallet/subnet/primary/examples/c-chain-export/main.go index fec55c899feb..a6b9a0c810b8 100644 --- a/wallet/subnet/primary/examples/c-chain-export/main.go +++ b/wallet/subnet/primary/examples/c-chain-export/main.go @@ -3,70 +3,70 @@ package main -import ( - "context" - "log" - "time" +// import ( +// "context" +// "log" +// "time" - "github.com/ava-labs/avalanchego/genesis" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary" -) +// "github.com/ava-labs/avalanchego/genesis" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary" +// ) -func main() { - key := genesis.EWOQKey - uri := primary.LocalAPIURI - kc := secp256k1fx.NewKeychain(key) - avaxAddr := key.Address() +// func main() { +// key := genesis.EWOQKey +// uri := primary.LocalAPIURI +// kc := secp256k1fx.NewKeychain(key) +// avaxAddr := key.Address() - ctx := context.Background() +// ctx := context.Background() - // MakeWallet fetches the available UTXOs owned by [kc] on the network that - // [uri] is hosting. - walletSyncStartTime := time.Now() - wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, - }) - if err != nil { - log.Fatalf("failed to initialize wallet: %s\n", err) - } - log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) +// // MakeWallet fetches the available UTXOs owned by [kc] on the network that +// // [uri] is hosting. +// walletSyncStartTime := time.Now() +// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ +// URI: uri, +// AVAXKeychain: kc, +// EthKeychain: kc, +// }) +// if err != nil { +// log.Fatalf("failed to initialize wallet: %s\n", err) +// } +// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) - // Get the P-chain wallet - pWallet := wallet.P() - cWallet := wallet.C() +// // Get the P-chain wallet +// pWallet := wallet.P() +// cWallet := wallet.C() - // Pull out useful constants to use when issuing transactions. - cChainID := cWallet.BlockchainID() - owner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - avaxAddr, - }, - } +// // Pull out useful constants to use when issuing transactions. +// cChainID := cWallet.BlockchainID() +// owner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// avaxAddr, +// }, +// } - exportStartTime := time.Now() - exportTx, err := cWallet.IssueExportTx( - constants.PlatformChainID, - []*secp256k1fx.TransferOutput{{ - Amt: units.Avax, - OutputOwners: owner, - }}, - ) - if err != nil { - log.Fatalf("failed to issue export transaction: %s\n", err) - } - log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) +// exportStartTime := time.Now() +// exportTx, err := cWallet.IssueExportTx( +// constants.PlatformChainID, +// []*secp256k1fx.TransferOutput{{ +// Amt: units.Avax, +// OutputOwners: owner, +// }}, +// ) +// if err != nil { +// log.Fatalf("failed to issue export transaction: %s\n", err) +// } +// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) - importStartTime := time.Now() - importTx, err := pWallet.IssueImportTx(cChainID, &owner) - if err != nil { - log.Fatalf("failed to issue import transaction: %s\n", err) - } - log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) -} +// importStartTime := time.Now() +// importTx, err := pWallet.IssueImportTx(cChainID, &owner) +// if err != nil { +// log.Fatalf("failed to issue import transaction: %s\n", err) +// } +// log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) +// } diff --git a/wallet/subnet/primary/examples/c-chain-import/main.go b/wallet/subnet/primary/examples/c-chain-import/main.go index b4dc4e603eb3..2d9b8a244cb0 100644 --- a/wallet/subnet/primary/examples/c-chain-import/main.go +++ b/wallet/subnet/primary/examples/c-chain-import/main.go @@ -3,75 +3,75 @@ package main -import ( - "context" - "log" - "time" +// import ( +// "context" +// "log" +// "time" - "github.com/ava-labs/coreth/plugin/evm" +// "github.com/ava-labs/coreth/plugin/evm" - "github.com/ava-labs/avalanchego/genesis" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary" -) +// "github.com/ava-labs/avalanchego/genesis" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary" +// ) -func main() { - key := genesis.EWOQKey - uri := primary.LocalAPIURI - kc := secp256k1fx.NewKeychain(key) - avaxAddr := key.Address() - ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) +// func main() { +// key := genesis.EWOQKey +// uri := primary.LocalAPIURI +// kc := secp256k1fx.NewKeychain(key) +// avaxAddr := key.Address() +// ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) - ctx := context.Background() +// ctx := context.Background() - // MakeWallet fetches the available UTXOs owned by [kc] on the network that - // [uri] is hosting. - walletSyncStartTime := time.Now() - wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, - }) - if err != nil { - log.Fatalf("failed to initialize wallet: %s\n", err) - } - log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) +// // MakeWallet fetches the available UTXOs owned by [kc] on the network that +// // [uri] is hosting. +// walletSyncStartTime := time.Now() +// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ +// URI: uri, +// AVAXKeychain: kc, +// EthKeychain: kc, +// }) +// if err != nil { +// log.Fatalf("failed to initialize wallet: %s\n", err) +// } +// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) - // Get the P-chain wallet - pWallet := wallet.P() - cWallet := wallet.C() +// // Get the P-chain wallet +// pWallet := wallet.P() +// cWallet := wallet.C() - // Pull out useful constants to use when issuing transactions. - cChainID := cWallet.BlockchainID() - avaxAssetID := cWallet.AVAXAssetID() - owner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - avaxAddr, - }, - } +// // Pull out useful constants to use when issuing transactions. +// cChainID := cWallet.BlockchainID() +// avaxAssetID := cWallet.AVAXAssetID() +// owner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// avaxAddr, +// }, +// } - exportStartTime := time.Now() - exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ - Asset: avax.Asset{ID: avaxAssetID}, - Out: &secp256k1fx.TransferOutput{ - Amt: units.Avax, - OutputOwners: owner, - }, - }}) - if err != nil { - log.Fatalf("failed to issue export transaction: %s\n", err) - } - log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) +// exportStartTime := time.Now() +// exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ +// Asset: avax.Asset{ID: avaxAssetID}, +// Out: &secp256k1fx.TransferOutput{ +// Amt: units.Avax, +// OutputOwners: owner, +// }, +// }}) +// if err != nil { +// log.Fatalf("failed to issue export transaction: %s\n", err) +// } +// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) - importStartTime := time.Now() - importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) - if err != nil { - log.Fatalf("failed to issue import transaction: %s\n", err) - } - log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) -} +// importStartTime := time.Now() +// importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) +// if err != nil { +// log.Fatalf("failed to issue import transaction: %s\n", err) +// } +// log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) +// } diff --git a/wallet/subnet/primary/examples/create-asset/main.go b/wallet/subnet/primary/examples/create-asset/main.go index 30804f083df6..0bccfbb5fc52 100644 --- a/wallet/subnet/primary/examples/create-asset/main.go +++ b/wallet/subnet/primary/examples/create-asset/main.go @@ -30,7 +30,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-chain/main.go b/wallet/subnet/primary/examples/create-chain/main.go index 5e6898a1b649..521a3cca53cf 100644 --- a/wallet/subnet/primary/examples/create-chain/main.go +++ b/wallet/subnet/primary/examples/create-chain/main.go @@ -41,9 +41,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/create-locked-stakeable/main.go b/wallet/subnet/primary/examples/create-locked-stakeable/main.go index e688968e9e8a..92f1b5cb0e1b 100644 --- a/wallet/subnet/primary/examples/create-locked-stakeable/main.go +++ b/wallet/subnet/primary/examples/create-locked-stakeable/main.go @@ -39,7 +39,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-subnet/main.go b/wallet/subnet/primary/examples/create-subnet/main.go index add98ea7931c..3e8d69bc016a 100644 --- a/wallet/subnet/primary/examples/create-subnet/main.go +++ b/wallet/subnet/primary/examples/create-subnet/main.go @@ -28,7 +28,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/remove-subnet-validator/main.go b/wallet/subnet/primary/examples/remove-subnet-validator/main.go index 2842c7c0a790..46f4b85124db 100644 --- a/wallet/subnet/primary/examples/remove-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/remove-subnet-validator/main.go @@ -38,9 +38,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/wallet.go b/wallet/subnet/primary/wallet.go index 54de390d029c..de50d12f866b 100644 --- a/wallet/subnet/primary/wallet.go +++ b/wallet/subnet/primary/wallet.go @@ -11,7 +11,6 @@ import ( "github.com/ava-labs/avalanchego/utils/crypto/keychain" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" @@ -23,13 +22,13 @@ var _ Wallet = (*wallet)(nil) type Wallet interface { P() p.Wallet X() x.Wallet - C() c.Wallet + // C() c.Wallet } type wallet struct { p p.Wallet x x.Wallet - c c.Wallet + // c c.Wallet } func (w *wallet) P() p.Wallet { @@ -40,16 +39,16 @@ func (w *wallet) X() x.Wallet { return w.x } -func (w *wallet) C() c.Wallet { - return w.c -} +// func (w *wallet) C() c.Wallet { +// return w.c +// } // Creates a new default wallet -func NewWallet(p p.Wallet, x x.Wallet, c c.Wallet) Wallet { +func NewWallet(p p.Wallet, x x.Wallet /*, c c.Wallet*/) Wallet { return &wallet{ p: p, x: x, - c: c, + // c: c, } } @@ -58,7 +57,7 @@ func NewWalletWithOptions(w Wallet, options ...common.Option) Wallet { return NewWallet( p.NewWalletWithOptions(w.P(), options...), x.NewWalletWithOptions(w.X(), options...), - c.NewWalletWithOptions(w.C(), options...), + // c.NewWalletWithOptions(w.C(), options...), ) } @@ -67,7 +66,7 @@ type WalletConfig struct { URI string // required // Keys to use for signing all transactions. AVAXKeychain keychain.Keychain // required - EthKeychain c.EthKeychain // required + // EthKeychain c.EthKeychain // required // Set of P-chain transactions that the wallet should know about to be able // to generate transactions. PChainTxs map[ids.ID]*txs.Tx // optional @@ -93,11 +92,11 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { return nil, err } - ethAddrs := config.EthKeychain.EthAddresses() - ethState, err := FetchEthState(ctx, config.URI, ethAddrs) - if err != nil { - return nil, err - } + // ethAddrs := config.EthKeychain.EthAddresses() + // ethState, err := FetchEthState(ctx, config.URI, ethAddrs) + // if err != nil { + // return nil, err + // } pChainTxs := config.PChainTxs if pChainTxs == nil { @@ -127,15 +126,15 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { xBuilder := x.NewBuilder(avaxAddrs, xBackend) xSigner := x.NewSigner(config.AVAXKeychain, xBackend) - cChainID := avaxState.CCTX.BlockchainID() - cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) - cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) - cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) - cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) + // cChainID := avaxState.CCTX.BlockchainID() + // cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) + // cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) + // cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) + // cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) return NewWallet( p.NewWallet(pBuilder, pSigner, avaxState.PClient, pBackend), x.NewWallet(xBuilder, xSigner, avaxState.XClient, xBackend), - c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), + // c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), ), nil } From 171a704493b3eb994535440c0289e5db98e022cb Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 1 Nov 2023 10:38:27 +0100 Subject: [PATCH 26/36] bumped coreth version --- go.mod | 25 + go.sum | 76 ++ node/node.go | 4 +- tests/e2e/c/dynamic_fees.go | 326 +++---- tests/e2e/c/interchain_workflow.go | 320 +++---- tests/e2e/e2e.go | 127 ++- tests/e2e/p/interchain_workflow.go | 444 +++++----- tests/e2e/x/interchain_workflow.go | 296 +++---- tests/fixture/testnet/config.go | 48 +- vms/example/xsvm/cmd/chain/create/cmd.go | 6 +- wallet/chain/c/backend.go | 300 +++---- wallet/chain/c/builder.go | 792 +++++++++--------- wallet/chain/c/builder_with_options.go | 136 +-- wallet/chain/c/context.go | 130 +-- wallet/chain/c/signer.go | 436 +++++----- wallet/chain/c/wallet.go | 402 ++++----- wallet/chain/c/wallet_with_options.go | 134 +-- wallet/subnet/primary/api.go | 119 +-- wallet/subnet/primary/example_test.go | 2 +- .../add-permissioned-subnet-validator/main.go | 6 +- .../examples/add-primary-validator/main.go | 2 +- .../primary/examples/c-chain-export/main.go | 118 +-- .../primary/examples/c-chain-import/main.go | 126 +-- .../primary/examples/create-asset/main.go | 2 +- .../primary/examples/create-chain/main.go | 6 +- .../examples/create-locked-stakeable/main.go | 2 +- .../primary/examples/create-subnet/main.go | 2 +- .../examples/remove-subnet-validator/main.go | 6 +- wallet/subnet/primary/wallet.go | 41 +- 29 files changed, 2270 insertions(+), 2164 deletions(-) diff --git a/go.mod b/go.mod index 40d59d0cb294..5ac8c490c12a 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/DataDog/zstd v1.5.2 github.com/Microsoft/go-winio v0.5.2 github.com/NYTimes/gziphandler v1.1.1 + github.com/ava-labs/coreth v0.12.8-0.20231101092910-57d47c2ced23 github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 github.com/btcsuite/btcd/btcutil v1.1.3 github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 @@ -71,6 +72,7 @@ require ( require ( github.com/BurntSushi/toml v1.2.1 // indirect + github.com/VictoriaMetrics/fastcache v1.10.0 // indirect github.com/benbjohnson/clock v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect @@ -79,26 +81,44 @@ require ( github.com/cockroachdb/errors v1.9.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/redact v1.1.3 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set/v2 v2.1.0 // indirect + github.com/dlclark/regexp2 v1.7.0 // indirect + github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect + github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/frankban/quicktest v1.14.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect + github.com/go-stack/stack v1.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/go-cmp v0.5.9 // indirect + github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 // indirect + github.com/hashicorp/go-bexpr v0.1.10 // indirect + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/klauspost/compress v1.15.15 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/magiconair/properties v1.8.6 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mitchellh/pointerstructure v1.2.0 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect @@ -106,12 +126,17 @@ require ( github.com/prometheus/common v0.39.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sanity-io/litter v1.5.1 // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/status-im/keycard-go v0.2.0 // indirect github.com/subosito/gotenv v1.3.0 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/zondax/hid v0.9.1 // indirect github.com/zondax/ledger-go v0.14.1 // indirect diff --git a/go.sum b/go.sum index 09e5526b3f20..70e720bf7621 100644 --- a/go.sum +++ b/go.sum @@ -52,12 +52,18 @@ github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cq github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= +github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY= +github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/ava-labs/coreth v0.12.8-0.20231101092910-57d47c2ced23 h1:PiwqnH1dJXSM/RVoRIF37xs4Nkh6U+eP+P0lbvkpnvE= +github.com/ava-labs/coreth v0.12.8-0.20231101092910-57d47c2ced23/go.mod h1:7OR8MAm9etvJ7WaoSsR+wgZvIn+4Gkpas95nsvN7pHc= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 h1:EdxD90j5sClfL5Ngpz2TlnbnkNYdFPDXa0jDOjam65c= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7/go.mod h1:XhiXSrh90sHUbkERzaxEftCmUz53eCijshDLZ4fByVM= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= @@ -94,13 +100,18 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -130,12 +141,16 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= +github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= @@ -146,6 +161,14 @@ github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6ps github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= +github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= +github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= +github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -162,6 +185,8 @@ github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2 github.com/ethereum/go-ethereum v1.12.0/go.mod h1:/oo2X/dZLJjf2mJ6YT9wcWxa4nNJDBKDBU6sFIpx1Gs= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -170,6 +195,8 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= @@ -193,7 +220,11 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= @@ -278,10 +309,14 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -302,11 +337,17 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 h1:kr3j8iIMR4ywO/O0rvksXaJvauGGCMg2zAZIiNZ9uIQ= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0/go.mod h1:ummNFgdgLhhX7aIiy35vVmQNS0rWXknfPE0qe6fmFXg= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw= +github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e/go.mod h1:j9cQbcqHQujT0oKJ38PylVfqohClLr3CvDC+Qcg+lhU= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8= @@ -318,6 +359,7 @@ github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3 github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -359,6 +401,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -366,6 +409,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= @@ -376,11 +420,17 @@ github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -389,8 +439,11 @@ github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -409,6 +462,8 @@ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -476,6 +531,8 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sanity-io/litter v1.5.1 h1:dwnrSypP6q56o3lFxTU+t2fwQ9A+U5qrXVO4Qg9KwVU= github.com/sanity-io/litter v1.5.1/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0= @@ -511,6 +568,8 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= +github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -540,10 +599,14 @@ github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITn github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= +github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -555,6 +618,8 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1: github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= @@ -564,6 +629,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= @@ -661,6 +727,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -706,6 +773,7 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -729,6 +797,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -793,8 +862,12 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -811,6 +884,7 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -874,6 +948,7 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -998,6 +1073,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= diff --git a/node/node.go b/node/node.go index 3b3974db0401..34293e85b0b6 100644 --- a/node/node.go +++ b/node/node.go @@ -25,7 +25,7 @@ import ( "go.uber.org/zap" - // coreth "github.com/ava-labs/coreth/plugin/evm" + coreth "github.com/ava-labs/coreth/plugin/evm" "github.com/ava-labs/avalanchego/api/admin" "github.com/ava-labs/avalanchego/api/auth" @@ -934,7 +934,7 @@ func (n *Node) initVMs() error { CreateAssetTxFee: n.Config.CreateAssetTxFee, }, }), - // vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), + vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), n.VMManager.RegisterFactory(context.TODO(), secp256k1fx.ID, &secp256k1fx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), nftfx.ID, &nftfx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), propertyfx.ID, &propertyfx.Factory{}), diff --git a/tests/e2e/c/dynamic_fees.go b/tests/e2e/c/dynamic_fees.go index 779c8670be37..edfbef2671a8 100644 --- a/tests/e2e/c/dynamic_fees.go +++ b/tests/e2e/c/dynamic_fees.go @@ -3,166 +3,166 @@ package c -// import ( -// "math/big" -// "strings" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/stretchr/testify/require" - -// "github.com/ethereum/go-ethereum/accounts/abi" -// "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/coreth/core/types" -// "github.com/ava-labs/coreth/params" -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/tests" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/tests/fixture/testnet" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// ) - -// // This test uses the compiled bin for `hashing.sol` as -// // well as its ABI contained in `hashing_contract.go`. - -// var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { -// require := require.New(ginkgo.GinkgoT()) - -// // Need a gas limit much larger than the standard 21_000 to enable -// // the contract to induce a gas price increase -// const largeGasLimit = uint64(8_000_000) - -// // TODO(marun) What is the significance of this value? -// gasTip := big.NewInt(1000 * params.GWei) - -// ginkgo.It("should ensure that the gas price is affected by load", func() { -// ginkgo.By("creating a new private network to ensure isolation from other tests") -// privateNetwork := e2e.Env.NewPrivateNetwork() - -// ginkgo.By("allocating a pre-funded key") -// key := privateNetwork.GetConfig().FundedKeys[0] -// ethAddress := evm.GetEthAddress(key) - -// ginkgo.By("initializing a coreth client") -// node := privateNetwork.GetNodes()[0] -// nodeURI := testnet.NodeURI{ -// NodeID: node.GetID(), -// URI: node.GetProcessContext().URI, -// } -// ethClient := e2e.Env.NewEthClient(nodeURI) - -// ginkgo.By("initializing a transaction signer") -// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) -// require.NoError(err) -// signer := types.NewEIP155Signer(cChainID) -// ecdsaKey := key.ToECDSA() -// sign := func(tx *types.Transaction) *types.Transaction { -// signedTx, err := types.SignTx(tx, signer, ecdsaKey) -// require.NoError(err) -// return signedTx -// } - -// var contractAddress common.Address -// ginkgo.By("deploying an expensive contract", func() { -// // Create transaction -// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) -// require.NoError(err) -// compiledContract := common.Hex2Bytes(hashingCompiledContract) -// tx := types.NewTx(&types.LegacyTx{ -// Nonce: nonce, -// GasPrice: gasTip, -// Gas: largeGasLimit, -// Value: common.Big0, -// Data: compiledContract, -// }) - -// // Send the transaction and wait for acceptance -// signedTx := sign(tx) -// receipt := e2e.SendEthTransaction(ethClient, signedTx) - -// contractAddress = receipt.ContractAddress -// }) - -// var gasPrice *big.Int -// ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { -// // Evaluate the bytes representation of the contract -// hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) -// require.NoError(err) -// contractData, err := hashingABI.Pack("hashIt") -// require.NoError(err) - -// var initialGasPrice *big.Int -// e2e.Eventually(func() bool { -// // Check the gas price -// var err error -// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) -// require.NoError(err) -// if initialGasPrice == nil { -// initialGasPrice = gasPrice -// tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) -// } else if gasPrice.Cmp(initialGasPrice) > 0 { -// // Gas price has increased -// tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) -// return true -// } - -// // Create the transaction -// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) -// require.NoError(err) -// tx := types.NewTx(&types.LegacyTx{ -// Nonce: nonce, -// GasPrice: gasTip, -// Gas: largeGasLimit, -// To: &contractAddress, -// Value: common.Big0, -// Data: contractData, -// }) - -// // Send the transaction and wait for acceptance -// signedTx := sign(tx) -// _ = e2e.SendEthTransaction(ethClient, signedTx) - -// // The gas price will be checked at the start of the next iteration -// return false -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") -// }) - -// ginkgo.By("waiting for the gas price to decrease...", func() { -// initialGasPrice := gasPrice -// e2e.Eventually(func() bool { -// var err error -// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) -// require.NoError(err) -// tests.Outf("{{blue}}.{{/}}") -// return initialGasPrice.Cmp(gasPrice) > 0 -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") -// tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) -// }) - -// ginkgo.By("sending funds at the current gas price", func() { -// // Create a recipient address -// recipientKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) -// recipientEthAddress := evm.GetEthAddress(recipientKey) - -// // Create transaction -// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) -// require.NoError(err) -// tx := types.NewTx(&types.LegacyTx{ -// Nonce: nonce, -// GasPrice: gasPrice, -// Gas: e2e.DefaultGasLimit, -// To: &recipientEthAddress, -// Value: common.Big0, -// }) - -// // Send the transaction and wait for acceptance -// signedTx := sign(tx) -// _ = e2e.SendEthTransaction(ethClient, signedTx) -// }) - -// e2e.CheckBootstrapIsPossible(privateNetwork) -// }) -// }) +import ( + "math/big" + "strings" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/coreth/params" + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/tests" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/tests/fixture/testnet" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +) + +// This test uses the compiled bin for `hashing.sol` as +// well as its ABI contained in `hashing_contract.go`. + +var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { + require := require.New(ginkgo.GinkgoT()) + + // Need a gas limit much larger than the standard 21_000 to enable + // the contract to induce a gas price increase + const largeGasLimit = uint64(8_000_000) + + // TODO(marun) What is the significance of this value? + gasTip := big.NewInt(1000 * params.GWei) + + ginkgo.It("should ensure that the gas price is affected by load", func() { + ginkgo.By("creating a new private network to ensure isolation from other tests") + privateNetwork := e2e.Env.NewPrivateNetwork() + + ginkgo.By("allocating a pre-funded key") + key := privateNetwork.GetConfig().FundedKeys[0] + ethAddress := evm.GetEthAddress(key) + + ginkgo.By("initializing a coreth client") + node := privateNetwork.GetNodes()[0] + nodeURI := testnet.NodeURI{ + NodeID: node.GetID(), + URI: node.GetProcessContext().URI, + } + ethClient := e2e.Env.NewEthClient(nodeURI) + + ginkgo.By("initializing a transaction signer") + cChainID, err := ethClient.ChainID(e2e.DefaultContext()) + require.NoError(err) + signer := types.NewEIP155Signer(cChainID) + ecdsaKey := key.ToECDSA() + sign := func(tx *types.Transaction) *types.Transaction { + signedTx, err := types.SignTx(tx, signer, ecdsaKey) + require.NoError(err) + return signedTx + } + + var contractAddress common.Address + ginkgo.By("deploying an expensive contract", func() { + // Create transaction + nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) + require.NoError(err) + compiledContract := common.Hex2Bytes(hashingCompiledContract) + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + GasPrice: gasTip, + Gas: largeGasLimit, + Value: common.Big0, + Data: compiledContract, + }) + + // Send the transaction and wait for acceptance + signedTx := sign(tx) + receipt := e2e.SendEthTransaction(ethClient, signedTx) + + contractAddress = receipt.ContractAddress + }) + + var gasPrice *big.Int + ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { + // Evaluate the bytes representation of the contract + hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) + require.NoError(err) + contractData, err := hashingABI.Pack("hashIt") + require.NoError(err) + + var initialGasPrice *big.Int + e2e.Eventually(func() bool { + // Check the gas price + var err error + gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) + require.NoError(err) + if initialGasPrice == nil { + initialGasPrice = gasPrice + tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) + } else if gasPrice.Cmp(initialGasPrice) > 0 { + // Gas price has increased + tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) + return true + } + + // Create the transaction + nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) + require.NoError(err) + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + GasPrice: gasTip, + Gas: largeGasLimit, + To: &contractAddress, + Value: common.Big0, + Data: contractData, + }) + + // Send the transaction and wait for acceptance + signedTx := sign(tx) + _ = e2e.SendEthTransaction(ethClient, signedTx) + + // The gas price will be checked at the start of the next iteration + return false + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") + }) + + ginkgo.By("waiting for the gas price to decrease...", func() { + initialGasPrice := gasPrice + e2e.Eventually(func() bool { + var err error + gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) + require.NoError(err) + tests.Outf("{{blue}}.{{/}}") + return initialGasPrice.Cmp(gasPrice) > 0 + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") + tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) + }) + + ginkgo.By("sending funds at the current gas price", func() { + // Create a recipient address + recipientKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + recipientEthAddress := evm.GetEthAddress(recipientKey) + + // Create transaction + nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) + require.NoError(err) + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + GasPrice: gasPrice, + Gas: e2e.DefaultGasLimit, + To: &recipientEthAddress, + Value: common.Big0, + }) + + // Send the transaction and wait for acceptance + signedTx := sign(tx) + _ = e2e.SendEthTransaction(ethClient, signedTx) + }) + + e2e.CheckBootstrapIsPossible(privateNetwork) + }) +}) diff --git a/tests/e2e/c/interchain_workflow.go b/tests/e2e/c/interchain_workflow.go index d13c4b8db1ce..8bed85eb1bd9 100644 --- a/tests/e2e/c/interchain_workflow.go +++ b/tests/e2e/c/interchain_workflow.go @@ -3,163 +3,163 @@ package c -// import ( -// "math/big" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/stretchr/testify/require" - -// "github.com/ava-labs/coreth/core/types" -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { -// require := require.New(ginkgo.GinkgoT()) - -// const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer - -// ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { -// ginkgo.By("initializing a new eth client") -// // Select a random node URI to use for both the eth client and -// // the wallet to avoid having to verify that all nodes are at -// // the same height before initializing the wallet. -// nodeURI := e2e.Env.GetRandomNodeURI() -// ethClient := e2e.Env.NewEthClient(nodeURI) - -// ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") -// senderKey := e2e.Env.AllocateFundedKey() -// senderEthAddress := evm.GetEthAddress(senderKey) -// recipientKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) -// recipientEthAddress := evm.GetEthAddress(recipientKey) - -// ginkgo.By("sending funds from one address to another on the C-Chain", func() { -// // Create transaction -// acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) -// require.NoError(err) -// gasPrice := e2e.SuggestGasPrice(ethClient) -// tx := types.NewTransaction( -// acceptedNonce, -// recipientEthAddress, -// big.NewInt(int64(txAmount)), -// e2e.DefaultGasLimit, -// gasPrice, -// nil, -// ) - -// // Sign transaction -// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) -// require.NoError(err) -// signer := types.NewEIP155Signer(cChainID) -// signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) -// require.NoError(err) - -// _ = e2e.SendEthTransaction(ethClient, signedTx) - -// ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") -// e2e.Eventually(func() bool { -// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) -// require.NoError(err) -// return balance.Cmp(big.NewInt(0)) > 0 -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") -// }) - -// // Wallet must be initialized after sending funds on the -// // C-Chain with the same node URI to ensure wallet state -// // matches on-chain state. -// ginkgo.By("initializing a keychain and associated wallet") -// keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) -// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) -// xWallet := baseWallet.X() -// cWallet := baseWallet.C() -// pWallet := baseWallet.P() - -// ginkgo.By("defining common configuration") -// avaxAssetID := xWallet.AVAXAssetID() -// // Use the same owner for import funds to X-Chain and P-Chain -// recipientOwner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// recipientKey.Address(), -// }, -// } -// // Use the same outputs for both X-Chain and P-Chain exports -// exportOutputs := []*secp256k1fx.TransferOutput{ -// { -// Amt: txAmount, -// OutputOwners: secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// keychain.Keys[0].Address(), -// }, -// }, -// }, -// } - -// ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { -// _, err := cWallet.IssueExportTx( -// xWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { -// _, err := xWallet.IssueImportTx( -// cWallet.BlockchainID(), -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { -// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { -// _, err := cWallet.IssueExportTx( -// constants.PlatformChainID, -// exportOutputs, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { -// _, err = pWallet.IssueImportTx( -// cWallet.BlockchainID(), -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { -// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) -// }) -// }) +import ( + "math/big" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { + require := require.New(ginkgo.GinkgoT()) + + const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer + + ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { + ginkgo.By("initializing a new eth client") + // Select a random node URI to use for both the eth client and + // the wallet to avoid having to verify that all nodes are at + // the same height before initializing the wallet. + nodeURI := e2e.Env.GetRandomNodeURI() + ethClient := e2e.Env.NewEthClient(nodeURI) + + ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") + senderKey := e2e.Env.AllocateFundedKey() + senderEthAddress := evm.GetEthAddress(senderKey) + recipientKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + recipientEthAddress := evm.GetEthAddress(recipientKey) + + ginkgo.By("sending funds from one address to another on the C-Chain", func() { + // Create transaction + acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) + require.NoError(err) + gasPrice := e2e.SuggestGasPrice(ethClient) + tx := types.NewTransaction( + acceptedNonce, + recipientEthAddress, + big.NewInt(int64(txAmount)), + e2e.DefaultGasLimit, + gasPrice, + nil, + ) + + // Sign transaction + cChainID, err := ethClient.ChainID(e2e.DefaultContext()) + require.NoError(err) + signer := types.NewEIP155Signer(cChainID) + signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) + require.NoError(err) + + _ = e2e.SendEthTransaction(ethClient, signedTx) + + ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") + e2e.Eventually(func() bool { + balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) + require.NoError(err) + return balance.Cmp(big.NewInt(0)) > 0 + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") + }) + + // Wallet must be initialized after sending funds on the + // C-Chain with the same node URI to ensure wallet state + // matches on-chain state. + ginkgo.By("initializing a keychain and associated wallet") + keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) + baseWallet := e2e.Env.NewWallet(keychain, nodeURI) + xWallet := baseWallet.X() + cWallet := baseWallet.C() + pWallet := baseWallet.P() + + ginkgo.By("defining common configuration") + avaxAssetID := xWallet.AVAXAssetID() + // Use the same owner for import funds to X-Chain and P-Chain + recipientOwner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + recipientKey.Address(), + }, + } + // Use the same outputs for both X-Chain and P-Chain exports + exportOutputs := []*secp256k1fx.TransferOutput{ + { + Amt: txAmount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + keychain.Keys[0].Address(), + }, + }, + }, + } + + ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { + _, err := cWallet.IssueExportTx( + xWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { + _, err := xWallet.IssueImportTx( + cWallet.BlockchainID(), + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { + balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { + _, err := cWallet.IssueExportTx( + constants.PlatformChainID, + exportOutputs, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { + _, err = pWallet.IssueImportTx( + cWallet.BlockchainID(), + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { + balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) + }) +}) diff --git a/tests/e2e/e2e.go b/tests/e2e/e2e.go index e69e244d3ee3..130f33f1197c 100644 --- a/tests/e2e/e2e.go +++ b/tests/e2e/e2e.go @@ -7,25 +7,22 @@ package e2e import ( "context" "encoding/json" - "path/filepath" - - // "errors" - // "fmt" - // "math/big" + "errors" + "fmt" + "math/big" "math/rand" "os" - - // "path/filepath" - // "strings" + "path/filepath" + "strings" "time" ginkgo "github.com/onsi/ginkgo/v2" "github.com/stretchr/testify/require" - // "github.com/ava-labs/coreth/core/types" - // "github.com/ava-labs/coreth/ethclient" - // "github.com/ava-labs/coreth/interfaces" + "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/coreth/ethclient" + "github.com/ava-labs/coreth/interfaces" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/tests" @@ -137,7 +134,7 @@ func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain, nodeURI tes baseWallet, err := primary.MakeWallet(DefaultContext(), &primary.WalletConfig{ URI: nodeURI.URI, AVAXKeychain: keychain, - // EthKeychain: keychain, + EthKeychain: keychain, }) te.require.NoError(err) return primary.NewWalletWithOptions( @@ -150,16 +147,16 @@ func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain, nodeURI tes ) } -// // Create a new eth client targeting the specified node URI. -// // TODO(marun) Make this a regular function. -// func (te *TestEnvironment) NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { -// tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) -// nodeAddress := strings.Split(nodeURI.URI, "//")[1] -// uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) -// client, err := ethclient.Dial(uri) -// te.require.NoError(err) -// return client -// } +// Create a new eth client targeting the specified node URI. +// TODO(marun) Make this a regular function. +func (te *TestEnvironment) NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { + tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) + nodeAddress := strings.Split(nodeURI.URI, "//")[1] + uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) + client, err := ethclient.Dial(uri) + te.require.NoError(err) + return client +} // Create a new private network that is not shared with other tests. func (te *TestEnvironment) NewPrivateNetwork() testnet.Network { @@ -234,49 +231,49 @@ func WaitForHealthy(node testnet.Node) { require.NoError(ginkgo.GinkgoT(), testnet.WaitForHealthy(DefaultContext(), node)) } -// // Sends an eth transaction, waits for the transaction receipt to be issued -// // and checks that the receipt indicates success. -// func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { -// require := require.New(ginkgo.GinkgoT()) - -// txID := signedTx.Hash() -// tests.Outf(" sending eth transaction with ID: %s\n", txID) - -// require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) - -// // Wait for the receipt -// var receipt *types.Receipt -// Eventually(func() bool { -// var err error -// receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) -// if errors.Is(err, interfaces.NotFound) { -// return false // Transaction is still pending -// } -// require.NoError(err) -// return true -// }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") - -// require.Equal(receipt.Status, types.ReceiptStatusSuccessful) -// return receipt -// } - -// // Determines the suggested gas price for the configured client that will -// // maximize the chances of transaction acceptance. -// func SuggestGasPrice(ethClient ethclient.Client) *big.Int { -// gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) -// require.NoError(ginkgo.GinkgoT(), err) -// // Double the suggested gas price to maximize the chances of -// // acceptance. Maybe this can be revisited pending resolution of -// // https://github.com/ava-labs/coreth/issues/314. -// gasPrice.Add(gasPrice, gasPrice) -// return gasPrice -// } - -// // Helper simplifying use via an option of a gas price appropriate for testing. -// func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { -// baseFee := SuggestGasPrice(ethClient) -// return common.WithBaseFee(baseFee) -// } +// Sends an eth transaction, waits for the transaction receipt to be issued +// and checks that the receipt indicates success. +func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { + require := require.New(ginkgo.GinkgoT()) + + txID := signedTx.Hash() + tests.Outf(" sending eth transaction with ID: %s\n", txID) + + require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) + + // Wait for the receipt + var receipt *types.Receipt + Eventually(func() bool { + var err error + receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) + if errors.Is(err, interfaces.NotFound) { + return false // Transaction is still pending + } + require.NoError(err) + return true + }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") + + require.Equal(receipt.Status, types.ReceiptStatusSuccessful) + return receipt +} + +// Determines the suggested gas price for the configured client that will +// maximize the chances of transaction acceptance. +func SuggestGasPrice(ethClient ethclient.Client) *big.Int { + gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) + require.NoError(ginkgo.GinkgoT(), err) + // Double the suggested gas price to maximize the chances of + // acceptance. Maybe this can be revisited pending resolution of + // https://github.com/ava-labs/coreth/issues/314. + gasPrice.Add(gasPrice, gasPrice) + return gasPrice +} + +// Helper simplifying use via an option of a gas price appropriate for testing. +func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { + baseFee := SuggestGasPrice(ethClient) + return common.WithBaseFee(baseFee) +} // Verify that a new node can bootstrap into the network. func CheckBootstrapIsPossible(network testnet.Network) { diff --git a/tests/e2e/p/interchain_workflow.go b/tests/e2e/p/interchain_workflow.go index d3715c254e90..729418adbd97 100644 --- a/tests/e2e/p/interchain_workflow.go +++ b/tests/e2e/p/interchain_workflow.go @@ -3,225 +3,225 @@ package p -// import ( -// "math/big" -// "time" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/spf13/cast" - -// "github.com/stretchr/testify/require" - -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/api/info" -// "github.com/ava-labs/avalanchego/config" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/tests/fixture/testnet" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/platformvm/reward" -// "github.com/ava-labs/avalanchego/vms/platformvm/txs" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { -// require := require.New(ginkgo.GinkgoT()) - -// const ( -// transferAmount = 10 * units.Avax -// weight = 2_000 * units.Avax // Used for both validation and delegation -// ) - -// ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { -// network := e2e.Env.GetNetwork() - -// ginkgo.By("checking that the network has a compatible minimum stake duration", func() { -// minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) -// require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) -// }) - -// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") -// recipientKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) -// keychain := e2e.Env.NewKeychain(1) -// keychain.Add(recipientKey) -// nodeURI := e2e.Env.GetRandomNodeURI() -// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) -// xWallet := baseWallet.X() -// cWallet := baseWallet.C() -// pWallet := baseWallet.P() - -// ginkgo.By("defining common configuration") -// recipientEthAddress := evm.GetEthAddress(recipientKey) -// avaxAssetID := xWallet.AVAXAssetID() -// // Use the same owner for sending to X-Chain and importing funds to P-Chain -// recipientOwner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// recipientKey.Address(), -// }, -// } -// // Use the same outputs for both X-Chain and C-Chain exports -// exportOutputs := []*avax.TransferableOutput{ -// { -// Asset: avax.Asset{ -// ID: avaxAssetID, -// }, -// Out: &secp256k1fx.TransferOutput{ -// Amt: transferAmount, -// OutputOwners: secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// keychain.Keys[0].Address(), -// }, -// }, -// }, -// }, -// } - -// ginkgo.By("adding new node and waiting for it to report healthy") -// node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) -// e2e.WaitForHealthy(node) - -// ginkgo.By("retrieving new node's id and pop") -// infoClient := info.NewClient(node.GetProcessContext().URI) -// nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) -// require.NoError(err) - -// ginkgo.By("adding the new node as a validator", func() { -// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) -// // Validation duration doesn't actually matter to this -// // test - it is only ensuring that adding a validator -// // doesn't break interchain transfer. -// endTime := startTime.Add(30 * time.Second) - -// rewardKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) - -// const ( -// delegationPercent = 0.10 // 10% -// delegationShare = reward.PercentDenominator * delegationPercent -// ) - -// _, err = pWallet.IssueAddPermissionlessValidatorTx( -// &txs.SubnetValidator{ -// Validator: txs.Validator{ -// NodeID: nodeID, -// Start: uint64(startTime.Unix()), -// End: uint64(endTime.Unix()), -// Wght: weight, -// }, -// Subnet: constants.PrimaryNetworkID, -// }, -// nodePOP, -// pWallet.AVAXAssetID(), -// &secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{rewardKey.Address()}, -// }, -// &secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{rewardKey.Address()}, -// }, -// delegationShare, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("adding a delegator to the new node", func() { -// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) -// // Delegation duration doesn't actually matter to this -// // test - it is only ensuring that adding a delegator -// // doesn't break interchain transfer. -// endTime := startTime.Add(15 * time.Second) - -// rewardKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) - -// _, err = pWallet.IssueAddPermissionlessDelegatorTx( -// &txs.SubnetValidator{ -// Validator: txs.Validator{ -// NodeID: nodeID, -// Start: uint64(startTime.Unix()), -// End: uint64(endTime.Unix()), -// Wght: weight, -// }, -// Subnet: constants.PrimaryNetworkID, -// }, -// pWallet.AVAXAssetID(), -// &secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{rewardKey.Address()}, -// }, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { -// _, err := pWallet.IssueExportTx( -// xWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { -// _, err := xWallet.IssueImportTx( -// constants.PlatformChainID, -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { -// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { -// _, err := pWallet.IssueExportTx( -// cWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("initializing a new eth client") -// ethClient := e2e.Env.NewEthClient(nodeURI) - -// ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { -// _, err := cWallet.IssueImportTx( -// constants.PlatformChainID, -// recipientEthAddress, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") -// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) -// require.NoError(err) -// require.Positive(balance.Cmp(big.NewInt(0))) - -// ginkgo.By("stopping validator node to free up resources for a bootstrap check") -// require.NoError(node.Stop()) - -// e2e.CheckBootstrapIsPossible(network) -// }) -// }) +import ( + "math/big" + "time" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/spf13/cast" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/api/info" + "github.com/ava-labs/avalanchego/config" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/tests/fixture/testnet" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/platformvm/reward" + "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { + require := require.New(ginkgo.GinkgoT()) + + const ( + transferAmount = 10 * units.Avax + weight = 2_000 * units.Avax // Used for both validation and delegation + ) + + ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { + network := e2e.Env.GetNetwork() + + ginkgo.By("checking that the network has a compatible minimum stake duration", func() { + minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) + require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) + }) + + ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") + recipientKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + keychain := e2e.Env.NewKeychain(1) + keychain.Add(recipientKey) + nodeURI := e2e.Env.GetRandomNodeURI() + baseWallet := e2e.Env.NewWallet(keychain, nodeURI) + xWallet := baseWallet.X() + cWallet := baseWallet.C() + pWallet := baseWallet.P() + + ginkgo.By("defining common configuration") + recipientEthAddress := evm.GetEthAddress(recipientKey) + avaxAssetID := xWallet.AVAXAssetID() + // Use the same owner for sending to X-Chain and importing funds to P-Chain + recipientOwner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + recipientKey.Address(), + }, + } + // Use the same outputs for both X-Chain and C-Chain exports + exportOutputs := []*avax.TransferableOutput{ + { + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: transferAmount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + keychain.Keys[0].Address(), + }, + }, + }, + }, + } + + ginkgo.By("adding new node and waiting for it to report healthy") + node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) + e2e.WaitForHealthy(node) + + ginkgo.By("retrieving new node's id and pop") + infoClient := info.NewClient(node.GetProcessContext().URI) + nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) + require.NoError(err) + + ginkgo.By("adding the new node as a validator", func() { + startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) + // Validation duration doesn't actually matter to this + // test - it is only ensuring that adding a validator + // doesn't break interchain transfer. + endTime := startTime.Add(30 * time.Second) + + rewardKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + + const ( + delegationPercent = 0.10 // 10% + delegationShare = reward.PercentDenominator * delegationPercent + ) + + _, err = pWallet.IssueAddPermissionlessValidatorTx( + &txs.SubnetValidator{ + Validator: txs.Validator{ + NodeID: nodeID, + Start: uint64(startTime.Unix()), + End: uint64(endTime.Unix()), + Wght: weight, + }, + Subnet: constants.PrimaryNetworkID, + }, + nodePOP, + pWallet.AVAXAssetID(), + &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{rewardKey.Address()}, + }, + &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{rewardKey.Address()}, + }, + delegationShare, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("adding a delegator to the new node", func() { + startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) + // Delegation duration doesn't actually matter to this + // test - it is only ensuring that adding a delegator + // doesn't break interchain transfer. + endTime := startTime.Add(15 * time.Second) + + rewardKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + + _, err = pWallet.IssueAddPermissionlessDelegatorTx( + &txs.SubnetValidator{ + Validator: txs.Validator{ + NodeID: nodeID, + Start: uint64(startTime.Unix()), + End: uint64(endTime.Unix()), + Wght: weight, + }, + Subnet: constants.PrimaryNetworkID, + }, + pWallet.AVAXAssetID(), + &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{rewardKey.Address()}, + }, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { + _, err := pWallet.IssueExportTx( + xWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { + _, err := xWallet.IssueImportTx( + constants.PlatformChainID, + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { + balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { + _, err := pWallet.IssueExportTx( + cWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("initializing a new eth client") + ethClient := e2e.Env.NewEthClient(nodeURI) + + ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { + _, err := cWallet.IssueImportTx( + constants.PlatformChainID, + recipientEthAddress, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") + balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) + require.NoError(err) + require.Positive(balance.Cmp(big.NewInt(0))) + + ginkgo.By("stopping validator node to free up resources for a bootstrap check") + require.NoError(node.Stop()) + + e2e.CheckBootstrapIsPossible(network) + }) +}) diff --git a/tests/e2e/x/interchain_workflow.go b/tests/e2e/x/interchain_workflow.go index 3b7a4c988405..6d335199b5b9 100644 --- a/tests/e2e/x/interchain_workflow.go +++ b/tests/e2e/x/interchain_workflow.go @@ -3,151 +3,151 @@ package x -// import ( -// "math/big" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/stretchr/testify/require" - -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { -// require := require.New(ginkgo.GinkgoT()) - -// const transferAmount = 10 * units.Avax - -// ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { -// nodeURI := e2e.Env.GetRandomNodeURI() - -// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") -// recipientKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) -// keychain := e2e.Env.NewKeychain(1) -// keychain.Add(recipientKey) -// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) -// xWallet := baseWallet.X() -// cWallet := baseWallet.C() -// pWallet := baseWallet.P() - -// ginkgo.By("defining common configuration") -// recipientEthAddress := evm.GetEthAddress(recipientKey) -// avaxAssetID := xWallet.AVAXAssetID() -// // Use the same owner for sending to X-Chain and importing funds to P-Chain -// recipientOwner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// recipientKey.Address(), -// }, -// } -// // Use the same outputs for both C-Chain and P-Chain exports -// exportOutputs := []*avax.TransferableOutput{ -// { -// Asset: avax.Asset{ -// ID: avaxAssetID, -// }, -// Out: &secp256k1fx.TransferOutput{ -// Amt: transferAmount, -// OutputOwners: secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// keychain.Keys[0].Address(), -// }, -// }, -// }, -// }, -// } - -// ginkgo.By("sending funds from one address to another on the X-Chain", func() { -// _, err = xWallet.IssueBaseTx( -// []*avax.TransferableOutput{{ -// Asset: avax.Asset{ -// ID: avaxAssetID, -// }, -// Out: &secp256k1fx.TransferOutput{ -// Amt: transferAmount, -// OutputOwners: recipientOwner, -// }, -// }}, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { -// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { -// _, err := xWallet.IssueExportTx( -// cWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("initializing a new eth client") -// ethClient := e2e.Env.NewEthClient(nodeURI) - -// ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { -// _, err := cWallet.IssueImportTx( -// xWallet.BlockchainID(), -// recipientEthAddress, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") -// e2e.Eventually(func() bool { -// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) -// require.NoError(err) -// return balance.Cmp(big.NewInt(0)) > 0 -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") - -// ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { -// _, err := xWallet.IssueExportTx( -// constants.PlatformChainID, -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { -// _, err := pWallet.IssueImportTx( -// xWallet.BlockchainID(), -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { -// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) -// }) -// }) +import ( + "math/big" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { + require := require.New(ginkgo.GinkgoT()) + + const transferAmount = 10 * units.Avax + + ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { + nodeURI := e2e.Env.GetRandomNodeURI() + + ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") + recipientKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + keychain := e2e.Env.NewKeychain(1) + keychain.Add(recipientKey) + baseWallet := e2e.Env.NewWallet(keychain, nodeURI) + xWallet := baseWallet.X() + cWallet := baseWallet.C() + pWallet := baseWallet.P() + + ginkgo.By("defining common configuration") + recipientEthAddress := evm.GetEthAddress(recipientKey) + avaxAssetID := xWallet.AVAXAssetID() + // Use the same owner for sending to X-Chain and importing funds to P-Chain + recipientOwner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + recipientKey.Address(), + }, + } + // Use the same outputs for both C-Chain and P-Chain exports + exportOutputs := []*avax.TransferableOutput{ + { + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: transferAmount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + keychain.Keys[0].Address(), + }, + }, + }, + }, + } + + ginkgo.By("sending funds from one address to another on the X-Chain", func() { + _, err = xWallet.IssueBaseTx( + []*avax.TransferableOutput{{ + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: transferAmount, + OutputOwners: recipientOwner, + }, + }}, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { + balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { + _, err := xWallet.IssueExportTx( + cWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("initializing a new eth client") + ethClient := e2e.Env.NewEthClient(nodeURI) + + ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { + _, err := cWallet.IssueImportTx( + xWallet.BlockchainID(), + recipientEthAddress, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") + e2e.Eventually(func() bool { + balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) + require.NoError(err) + return balance.Cmp(big.NewInt(0)) > 0 + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") + + ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { + _, err := xWallet.IssueExportTx( + constants.PlatformChainID, + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { + _, err := pWallet.IssueImportTx( + xWallet.BlockchainID(), + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { + balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) + }) +}) diff --git a/tests/fixture/testnet/config.go b/tests/fixture/testnet/config.go index 7130ad290ab5..425aa646a690 100644 --- a/tests/fixture/testnet/config.go +++ b/tests/fixture/testnet/config.go @@ -15,9 +15,9 @@ import ( "github.com/spf13/cast" - // "github.com/ava-labs/coreth/core" - // "github.com/ava-labs/coreth/params" - // "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/coreth/core" + "github.com/ava-labs/coreth/params" + "github.com/ava-labs/coreth/plugin/evm" "github.com/ava-labs/avalanchego/config" "github.com/ava-labs/avalanchego/genesis" @@ -143,15 +143,15 @@ func (c *NetworkConfig) EnsureGenesis(networkID uint32, validatorIDs []ids.NodeI // Ensure pre-funded keys have arbitrary large balances on both chains to support testing xChainBalances := make(XChainBalanceMap, len(c.FundedKeys)) - // cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) + cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) for _, key := range c.FundedKeys { xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount - // cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ - // Balance: DefaultFundedKeyCChainAmount, - // } + cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ + Balance: DefaultFundedKeyCChainAmount, + } } - genesis, err := NewTestGenesis(networkID, xChainBalances /*cChainBalances,*/, validatorIDs) + genesis, err := NewTestGenesis(networkID, xChainBalances, cChainBalances, validatorIDs) if err != nil { return err } @@ -311,7 +311,7 @@ type XChainBalanceMap map[ids.ShortID]uint64 func NewTestGenesis( networkID uint32, xChainBalances XChainBalanceMap, - // cChainBalances core.GenesisAlloc, + cChainBalances core.GenesisAlloc, validatorIDs []ids.NodeID, ) (*genesis.UnparsedConfig, error) { // Validate inputs @@ -322,7 +322,7 @@ func NewTestGenesis( if len(validatorIDs) == 0 { return nil, errMissingValidatorsForGenesis } - if len(xChainBalances) == 0 /*|| len(cChainBalances) == 0*/ { + if len(xChainBalances) == 0 || len(cChainBalances) == 0 { return nil, errMissingBalancesForGenesis } @@ -394,20 +394,20 @@ func NewTestGenesis( ) } - // // Define C-Chain genesis - // cChainGenesis := &core.Genesis{ - // Config: ¶ms.ChainConfig{ - // ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary - // }, - // Difficulty: big.NewInt(0), // Difficulty is a mandatory field - // GasLimit: DefaultGasLimit, - // Alloc: cChainBalances, - // } - // cChainGenesisBytes, err := json.Marshal(cChainGenesis) - // if err != nil { - // return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) - // } - // config.CChainGenesis = string(cChainGenesisBytes) + // Define C-Chain genesis + cChainGenesis := &core.Genesis{ + Config: ¶ms.ChainConfig{ + ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary + }, + Difficulty: big.NewInt(0), // Difficulty is a mandatory field + GasLimit: DefaultGasLimit, + Alloc: cChainBalances, + } + cChainGenesisBytes, err := json.Marshal(cChainGenesis) + if err != nil { + return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) + } + config.CChainGenesis = string(cChainGenesisBytes) // Give staking rewards for initial validators to a random address. Any testing of staking rewards // will be easier to perform with nodes other than the initial validators since the timing of diff --git a/vms/example/xsvm/cmd/chain/create/cmd.go b/vms/example/xsvm/cmd/chain/create/cmd.go index 043b4298dcdf..1f00491a4ce6 100644 --- a/vms/example/xsvm/cmd/chain/create/cmd.go +++ b/vms/example/xsvm/cmd/chain/create/cmd.go @@ -42,9 +42,9 @@ func createFunc(c *cobra.Command, args []string) error { // that [uri] is hosting. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: config.URI, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: config.URI, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(config.SubnetID), }) if err != nil { diff --git a/wallet/chain/c/backend.go b/wallet/chain/c/backend.go index b88c8c643bc3..0a735116b646 100644 --- a/wallet/chain/c/backend.go +++ b/wallet/chain/c/backend.go @@ -3,153 +3,153 @@ package c -// import ( -// "errors" -// "fmt" -// "math/big" -// "sync" - -// stdcontext "context" - -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/database" -// "github.com/ava-labs/avalanchego/utils/math" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var ( -// _ Backend = (*backend)(nil) - -// errUnknownTxType = errors.New("unknown tx type") -// ) - -// // Backend defines the full interface required to support a C-chain wallet. -// type Backend interface { -// common.ChainUTXOs -// BuilderBackend -// SignerBackend - -// AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error -// } - -// type backend struct { -// Context -// common.ChainUTXOs - -// accountsLock sync.RWMutex -// accounts map[ethcommon.Address]*Account -// } - -// type Account struct { -// Balance *big.Int -// Nonce uint64 -// } - -// func NewBackend( -// ctx Context, -// utxos common.ChainUTXOs, -// accounts map[ethcommon.Address]*Account, -// ) Backend { -// return &backend{ -// Context: ctx, -// ChainUTXOs: utxos, -// accounts: accounts, -// } -// } - -// func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { -// switch tx := tx.UnsignedAtomicTx.(type) { -// case *evm.UnsignedImportTx: -// for _, input := range tx.ImportedInputs { -// utxoID := input.InputID() -// if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { -// return err -// } -// } - -// b.accountsLock.Lock() -// defer b.accountsLock.Unlock() - -// for _, output := range tx.Outs { -// account, ok := b.accounts[output.Address] -// if !ok { -// continue -// } - -// balance := new(big.Int).SetUint64(output.Amount) -// balance.Mul(balance, avaxConversionRate) -// account.Balance.Add(account.Balance, balance) -// } -// case *evm.UnsignedExportTx: -// txID := tx.ID() -// for i, out := range tx.ExportedOutputs { -// err := b.AddUTXO( -// ctx, -// tx.DestinationChain, -// &avax.UTXO{ -// UTXOID: avax.UTXOID{ -// TxID: txID, -// OutputIndex: uint32(i), -// }, -// Asset: avax.Asset{ID: out.AssetID()}, -// Out: out.Out, -// }, -// ) -// if err != nil { -// return err -// } -// } - -// b.accountsLock.Lock() -// defer b.accountsLock.Unlock() - -// for _, input := range tx.Ins { -// account, ok := b.accounts[input.Address] -// if !ok { -// continue -// } - -// balance := new(big.Int).SetUint64(input.Amount) -// balance.Mul(balance, avaxConversionRate) -// if account.Balance.Cmp(balance) == -1 { -// return errInsufficientFunds -// } -// account.Balance.Sub(account.Balance, balance) - -// newNonce, err := math.Add64(input.Nonce, 1) -// if err != nil { -// return err -// } -// account.Nonce = newNonce -// } -// default: -// return fmt.Errorf("%w: %T", errUnknownTxType, tx) -// } -// return nil -// } - -// func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { -// b.accountsLock.RLock() -// defer b.accountsLock.RUnlock() - -// account, exists := b.accounts[addr] -// if !exists { -// return nil, database.ErrNotFound -// } -// return account.Balance, nil -// } - -// func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { -// b.accountsLock.RLock() -// defer b.accountsLock.RUnlock() - -// account, exists := b.accounts[addr] -// if !exists { -// return 0, database.ErrNotFound -// } -// return account.Nonce, nil -// } +import ( + "errors" + "fmt" + "math/big" + "sync" + + stdcontext "context" + + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/utils/math" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var ( + _ Backend = (*backend)(nil) + + errUnknownTxType = errors.New("unknown tx type") +) + +// Backend defines the full interface required to support a C-chain wallet. +type Backend interface { + common.ChainUTXOs + BuilderBackend + SignerBackend + + AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error +} + +type backend struct { + Context + common.ChainUTXOs + + accountsLock sync.RWMutex + accounts map[ethcommon.Address]*Account +} + +type Account struct { + Balance *big.Int + Nonce uint64 +} + +func NewBackend( + ctx Context, + utxos common.ChainUTXOs, + accounts map[ethcommon.Address]*Account, +) Backend { + return &backend{ + Context: ctx, + ChainUTXOs: utxos, + accounts: accounts, + } +} + +func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { + switch tx := tx.UnsignedAtomicTx.(type) { + case *evm.UnsignedImportTx: + for _, input := range tx.ImportedInputs { + utxoID := input.InputID() + if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { + return err + } + } + + b.accountsLock.Lock() + defer b.accountsLock.Unlock() + + for _, output := range tx.Outs { + account, ok := b.accounts[output.Address] + if !ok { + continue + } + + balance := new(big.Int).SetUint64(output.Amount) + balance.Mul(balance, avaxConversionRate) + account.Balance.Add(account.Balance, balance) + } + case *evm.UnsignedExportTx: + txID := tx.ID() + for i, out := range tx.ExportedOutputs { + err := b.AddUTXO( + ctx, + tx.DestinationChain, + &avax.UTXO{ + UTXOID: avax.UTXOID{ + TxID: txID, + OutputIndex: uint32(i), + }, + Asset: avax.Asset{ID: out.AssetID()}, + Out: out.Out, + }, + ) + if err != nil { + return err + } + } + + b.accountsLock.Lock() + defer b.accountsLock.Unlock() + + for _, input := range tx.Ins { + account, ok := b.accounts[input.Address] + if !ok { + continue + } + + balance := new(big.Int).SetUint64(input.Amount) + balance.Mul(balance, avaxConversionRate) + if account.Balance.Cmp(balance) == -1 { + return errInsufficientFunds + } + account.Balance.Sub(account.Balance, balance) + + newNonce, err := math.Add64(input.Nonce, 1) + if err != nil { + return err + } + account.Nonce = newNonce + } + default: + return fmt.Errorf("%w: %T", errUnknownTxType, tx) + } + return nil +} + +func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { + b.accountsLock.RLock() + defer b.accountsLock.RUnlock() + + account, exists := b.accounts[addr] + if !exists { + return nil, database.ErrNotFound + } + return account.Balance, nil +} + +func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { + b.accountsLock.RLock() + defer b.accountsLock.RUnlock() + + account, exists := b.accounts[addr] + if !exists { + return 0, database.ErrNotFound + } + return account.Nonce, nil +} diff --git a/wallet/chain/c/builder.go b/wallet/chain/c/builder.go index c51d2647777e..d2d088e88a53 100644 --- a/wallet/chain/c/builder.go +++ b/wallet/chain/c/builder.go @@ -3,399 +3,399 @@ package c -// import ( -// "errors" -// "math/big" - -// stdcontext "context" - -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils" -// "github.com/ava-labs/avalanchego/utils/math" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// const avaxConversionRateInt = 1_000_000_000 - -// var ( -// _ Builder = (*builder)(nil) - -// errInsufficientFunds = errors.New("insufficient funds") - -// // avaxConversionRate is the conversion rate between the smallest -// // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest -// // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. -// // -// // This is only required for AVAX because the denomination of 1 AVAX is 9 -// // decimal places on the X and P chains, but is 18 decimal places within the -// // EVM. -// avaxConversionRate = big.NewInt(avaxConversionRateInt) -// ) - -// // Builder provides a convenient interface for building unsigned C-chain -// // transactions. -// type Builder interface { -// // GetBalance calculates the amount of AVAX that this builder has control -// // over. -// GetBalance( -// options ...common.Option, -// ) (*big.Int, error) - -// // GetImportableBalance calculates the amount of AVAX that this builder -// // could import from the provided chain. -// // -// // - [chainID] specifies the chain the funds are from. -// GetImportableBalance( -// chainID ids.ID, -// options ...common.Option, -// ) (uint64, error) - -// // NewImportTx creates an import transaction that attempts to consume all -// // the available UTXOs and import the funds to [to]. -// // -// // - [chainID] specifies the chain to be importing funds from. -// // - [to] specifies where to send the imported funds to. -// // - [baseFee] specifies the fee price willing to be paid by this tx. -// NewImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedImportTx, error) - -// // NewExportTx creates an export transaction that attempts to send all the -// // provided [outputs] to the requested [chainID]. -// // -// // - [chainID] specifies the chain to be exporting the funds to. -// // - [outputs] specifies the outputs to send to the [chainID]. -// // - [baseFee] specifies the fee price willing to be paid by this tx. -// NewExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedExportTx, error) -// } - -// // BuilderBackend specifies the required information needed to build unsigned -// // C-chain transactions. -// type BuilderBackend interface { -// Context - -// UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) -// Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) -// Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) -// } - -// type builder struct { -// avaxAddrs set.Set[ids.ShortID] -// ethAddrs set.Set[ethcommon.Address] -// backend BuilderBackend -// } - -// // NewBuilder returns a new transaction builder. -// // -// // - [avaxAddrs] is the set of addresses in the AVAX format that the builder -// // assumes can be used when signing the transactions in the future. -// // - [ethAddrs] is the set of addresses in the Eth format that the builder -// // assumes can be used when signing the transactions in the future. -// // - [backend] provides the required access to the chain's context and state -// // to build out the transactions. -// func NewBuilder( -// avaxAddrs set.Set[ids.ShortID], -// ethAddrs set.Set[ethcommon.Address], -// backend BuilderBackend, -// ) Builder { -// return &builder{ -// avaxAddrs: avaxAddrs, -// ethAddrs: ethAddrs, -// backend: backend, -// } -// } - -// func (b *builder) GetBalance( -// options ...common.Option, -// ) (*big.Int, error) { -// var ( -// ops = common.NewOptions(options) -// ctx = ops.Context() -// addrs = ops.EthAddresses(b.ethAddrs) -// totalBalance = new(big.Int) -// ) -// for addr := range addrs { -// balance, err := b.backend.Balance(ctx, addr) -// if err != nil { -// return nil, err -// } -// totalBalance.Add(totalBalance, balance) -// } - -// return totalBalance, nil -// } - -// func (b *builder) GetImportableBalance( -// chainID ids.ID, -// options ...common.Option, -// ) (uint64, error) { -// ops := common.NewOptions(options) -// utxos, err := b.backend.UTXOs(ops.Context(), chainID) -// if err != nil { -// return 0, err -// } - -// var ( -// addrs = ops.Addresses(b.avaxAddrs) -// minIssuanceTime = ops.MinIssuanceTime() -// avaxAssetID = b.backend.AVAXAssetID() -// balance uint64 -// ) -// for _, utxo := range utxos { -// amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) -// if !ok { -// continue -// } - -// newBalance, err := math.Add64(balance, amount) -// if err != nil { -// return 0, err -// } -// balance = newBalance -// } - -// return balance, nil -// } - -// func (b *builder) NewImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedImportTx, error) { -// ops := common.NewOptions(options) -// utxos, err := b.backend.UTXOs(ops.Context(), chainID) -// if err != nil { -// return nil, err -// } - -// var ( -// addrs = ops.Addresses(b.avaxAddrs) -// minIssuanceTime = ops.MinIssuanceTime() -// avaxAssetID = b.backend.AVAXAssetID() - -// importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) -// importedAmount uint64 -// ) -// for _, utxo := range utxos { -// amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) -// if !ok { -// continue -// } - -// importedInputs = append(importedInputs, &avax.TransferableInput{ -// UTXOID: utxo.UTXOID, -// Asset: utxo.Asset, -// In: &secp256k1fx.TransferInput{ -// Amt: amount, -// Input: secp256k1fx.Input{ -// SigIndices: inputSigIndices, -// }, -// }, -// }) - -// newImportedAmount, err := math.Add64(importedAmount, amount) -// if err != nil { -// return nil, err -// } -// importedAmount = newImportedAmount -// } - -// utils.Sort(importedInputs) -// tx := &evm.UnsignedImportTx{ -// NetworkID: b.backend.NetworkID(), -// BlockchainID: b.backend.BlockchainID(), -// SourceChain: chainID, -// ImportedInputs: importedInputs, -// } - -// // We must initialize the bytes of the tx to calculate the initial cost -// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} -// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { -// return nil, err -// } - -// gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) -// if err != nil { -// return nil, err -// } -// gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas - -// txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) -// if err != nil { -// return nil, err -// } - -// if importedAmount <= txFee { -// return nil, errInsufficientFunds -// } - -// tx.Outs = []evm.EVMOutput{{ -// Address: to, -// Amount: importedAmount - txFee, -// AssetID: avaxAssetID, -// }} -// return tx, nil -// } - -// func (b *builder) NewExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedExportTx, error) { -// var ( -// avaxAssetID = b.backend.AVAXAssetID() -// exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) -// exportedAmount uint64 -// ) -// for i, output := range outputs { -// exportedOutputs[i] = &avax.TransferableOutput{ -// Asset: avax.Asset{ID: avaxAssetID}, -// Out: output, -// } - -// newExportedAmount, err := math.Add64(exportedAmount, output.Amt) -// if err != nil { -// return nil, err -// } -// exportedAmount = newExportedAmount -// } - -// avax.SortTransferableOutputs(exportedOutputs, evm.Codec) -// tx := &evm.UnsignedExportTx{ -// NetworkID: b.backend.NetworkID(), -// BlockchainID: b.backend.BlockchainID(), -// DestinationChain: chainID, -// ExportedOutputs: exportedOutputs, -// } - -// // We must initialize the bytes of the tx to calculate the initial cost -// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} -// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { -// return nil, err -// } - -// cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) -// if err != nil { -// return nil, err -// } - -// initialFee, err := evm.CalculateDynamicFee(cost, baseFee) -// if err != nil { -// return nil, err -// } - -// amountToConsume, err := math.Add64(exportedAmount, initialFee) -// if err != nil { -// return nil, err -// } - -// var ( -// ops = common.NewOptions(options) -// ctx = ops.Context() -// addrs = ops.EthAddresses(b.ethAddrs) -// inputs = make([]evm.EVMInput, 0, addrs.Len()) -// ) -// for addr := range addrs { -// if amountToConsume == 0 { -// break -// } - -// prevFee, err := evm.CalculateDynamicFee(cost, baseFee) -// if err != nil { -// return nil, err -// } - -// newCost := cost + evm.EVMInputGas -// newFee, err := evm.CalculateDynamicFee(newCost, baseFee) -// if err != nil { -// return nil, err -// } - -// additionalFee := newFee - prevFee - -// balance, err := b.backend.Balance(ctx, addr) -// if err != nil { -// return nil, err -// } - -// // Since the asset is AVAX, we divide by the avaxConversionRate to -// // convert back to the correct denomination of AVAX that can be -// // exported. -// avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() - -// // If the balance for [addr] is insufficient to cover the additional -// // cost of adding an input to the transaction, skip adding the input -// // altogether. -// if avaxBalance <= additionalFee { -// continue -// } - -// // Update the cost for the next iteration -// cost = newCost - -// amountToConsume, err = math.Add64(amountToConsume, additionalFee) -// if err != nil { -// return nil, err -// } - -// nonce, err := b.backend.Nonce(ctx, addr) -// if err != nil { -// return nil, err -// } - -// inputAmount := math.Min(amountToConsume, avaxBalance) -// inputs = append(inputs, evm.EVMInput{ -// Address: addr, -// Amount: inputAmount, -// AssetID: avaxAssetID, -// Nonce: nonce, -// }) -// amountToConsume -= inputAmount -// } - -// if amountToConsume > 0 { -// return nil, errInsufficientFunds -// } - -// utils.Sort(inputs) -// tx.Ins = inputs -// return tx, nil -// } - -// func getSpendableAmount( -// utxo *avax.UTXO, -// addrs set.Set[ids.ShortID], -// minIssuanceTime uint64, -// avaxAssetID ids.ID, -// ) (uint64, []uint32, bool) { -// if utxo.Asset.ID != avaxAssetID { -// // Only AVAX can be imported -// return 0, nil, false -// } - -// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) -// if !ok { -// // Can't import an unknown transfer output type -// return 0, nil, false -// } - -// inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) -// return out.Amt, inputSigIndices, ok -// } +import ( + "errors" + "math/big" + + stdcontext "context" + + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils" + "github.com/ava-labs/avalanchego/utils/math" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +const avaxConversionRateInt = 1_000_000_000 + +var ( + _ Builder = (*builder)(nil) + + errInsufficientFunds = errors.New("insufficient funds") + + // avaxConversionRate is the conversion rate between the smallest + // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest + // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. + // + // This is only required for AVAX because the denomination of 1 AVAX is 9 + // decimal places on the X and P chains, but is 18 decimal places within the + // EVM. + avaxConversionRate = big.NewInt(avaxConversionRateInt) +) + +// Builder provides a convenient interface for building unsigned C-chain +// transactions. +type Builder interface { + // GetBalance calculates the amount of AVAX that this builder has control + // over. + GetBalance( + options ...common.Option, + ) (*big.Int, error) + + // GetImportableBalance calculates the amount of AVAX that this builder + // could import from the provided chain. + // + // - [chainID] specifies the chain the funds are from. + GetImportableBalance( + chainID ids.ID, + options ...common.Option, + ) (uint64, error) + + // NewImportTx creates an import transaction that attempts to consume all + // the available UTXOs and import the funds to [to]. + // + // - [chainID] specifies the chain to be importing funds from. + // - [to] specifies where to send the imported funds to. + // - [baseFee] specifies the fee price willing to be paid by this tx. + NewImportTx( + chainID ids.ID, + to ethcommon.Address, + baseFee *big.Int, + options ...common.Option, + ) (*evm.UnsignedImportTx, error) + + // NewExportTx creates an export transaction that attempts to send all the + // provided [outputs] to the requested [chainID]. + // + // - [chainID] specifies the chain to be exporting the funds to. + // - [outputs] specifies the outputs to send to the [chainID]. + // - [baseFee] specifies the fee price willing to be paid by this tx. + NewExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + baseFee *big.Int, + options ...common.Option, + ) (*evm.UnsignedExportTx, error) +} + +// BuilderBackend specifies the required information needed to build unsigned +// C-chain transactions. +type BuilderBackend interface { + Context + + UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) + Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) + Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) +} + +type builder struct { + avaxAddrs set.Set[ids.ShortID] + ethAddrs set.Set[ethcommon.Address] + backend BuilderBackend +} + +// NewBuilder returns a new transaction builder. +// +// - [avaxAddrs] is the set of addresses in the AVAX format that the builder +// assumes can be used when signing the transactions in the future. +// - [ethAddrs] is the set of addresses in the Eth format that the builder +// assumes can be used when signing the transactions in the future. +// - [backend] provides the required access to the chain's context and state +// to build out the transactions. +func NewBuilder( + avaxAddrs set.Set[ids.ShortID], + ethAddrs set.Set[ethcommon.Address], + backend BuilderBackend, +) Builder { + return &builder{ + avaxAddrs: avaxAddrs, + ethAddrs: ethAddrs, + backend: backend, + } +} + +func (b *builder) GetBalance( + options ...common.Option, +) (*big.Int, error) { + var ( + ops = common.NewOptions(options) + ctx = ops.Context() + addrs = ops.EthAddresses(b.ethAddrs) + totalBalance = new(big.Int) + ) + for addr := range addrs { + balance, err := b.backend.Balance(ctx, addr) + if err != nil { + return nil, err + } + totalBalance.Add(totalBalance, balance) + } + + return totalBalance, nil +} + +func (b *builder) GetImportableBalance( + chainID ids.ID, + options ...common.Option, +) (uint64, error) { + ops := common.NewOptions(options) + utxos, err := b.backend.UTXOs(ops.Context(), chainID) + if err != nil { + return 0, err + } + + var ( + addrs = ops.Addresses(b.avaxAddrs) + minIssuanceTime = ops.MinIssuanceTime() + avaxAssetID = b.backend.AVAXAssetID() + balance uint64 + ) + for _, utxo := range utxos { + amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) + if !ok { + continue + } + + newBalance, err := math.Add64(balance, amount) + if err != nil { + return 0, err + } + balance = newBalance + } + + return balance, nil +} + +func (b *builder) NewImportTx( + chainID ids.ID, + to ethcommon.Address, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedImportTx, error) { + ops := common.NewOptions(options) + utxos, err := b.backend.UTXOs(ops.Context(), chainID) + if err != nil { + return nil, err + } + + var ( + addrs = ops.Addresses(b.avaxAddrs) + minIssuanceTime = ops.MinIssuanceTime() + avaxAssetID = b.backend.AVAXAssetID() + + importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) + importedAmount uint64 + ) + for _, utxo := range utxos { + amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) + if !ok { + continue + } + + importedInputs = append(importedInputs, &avax.TransferableInput{ + UTXOID: utxo.UTXOID, + Asset: utxo.Asset, + In: &secp256k1fx.TransferInput{ + Amt: amount, + Input: secp256k1fx.Input{ + SigIndices: inputSigIndices, + }, + }, + }) + + newImportedAmount, err := math.Add64(importedAmount, amount) + if err != nil { + return nil, err + } + importedAmount = newImportedAmount + } + + utils.Sort(importedInputs) + tx := &evm.UnsignedImportTx{ + NetworkID: b.backend.NetworkID(), + BlockchainID: b.backend.BlockchainID(), + SourceChain: chainID, + ImportedInputs: importedInputs, + } + + // We must initialize the bytes of the tx to calculate the initial cost + wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} + if err := wrappedTx.Sign(evm.Codec, nil); err != nil { + return nil, err + } + + gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) + if err != nil { + return nil, err + } + gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas + + txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) + if err != nil { + return nil, err + } + + if importedAmount <= txFee { + return nil, errInsufficientFunds + } + + tx.Outs = []evm.EVMOutput{{ + Address: to, + Amount: importedAmount - txFee, + AssetID: avaxAssetID, + }} + return tx, nil +} + +func (b *builder) NewExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedExportTx, error) { + var ( + avaxAssetID = b.backend.AVAXAssetID() + exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) + exportedAmount uint64 + ) + for i, output := range outputs { + exportedOutputs[i] = &avax.TransferableOutput{ + Asset: avax.Asset{ID: avaxAssetID}, + Out: output, + } + + newExportedAmount, err := math.Add64(exportedAmount, output.Amt) + if err != nil { + return nil, err + } + exportedAmount = newExportedAmount + } + + avax.SortTransferableOutputs(exportedOutputs, evm.Codec) + tx := &evm.UnsignedExportTx{ + NetworkID: b.backend.NetworkID(), + BlockchainID: b.backend.BlockchainID(), + DestinationChain: chainID, + ExportedOutputs: exportedOutputs, + } + + // We must initialize the bytes of the tx to calculate the initial cost + wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} + if err := wrappedTx.Sign(evm.Codec, nil); err != nil { + return nil, err + } + + cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) + if err != nil { + return nil, err + } + + initialFee, err := evm.CalculateDynamicFee(cost, baseFee) + if err != nil { + return nil, err + } + + amountToConsume, err := math.Add64(exportedAmount, initialFee) + if err != nil { + return nil, err + } + + var ( + ops = common.NewOptions(options) + ctx = ops.Context() + addrs = ops.EthAddresses(b.ethAddrs) + inputs = make([]evm.EVMInput, 0, addrs.Len()) + ) + for addr := range addrs { + if amountToConsume == 0 { + break + } + + prevFee, err := evm.CalculateDynamicFee(cost, baseFee) + if err != nil { + return nil, err + } + + newCost := cost + evm.EVMInputGas + newFee, err := evm.CalculateDynamicFee(newCost, baseFee) + if err != nil { + return nil, err + } + + additionalFee := newFee - prevFee + + balance, err := b.backend.Balance(ctx, addr) + if err != nil { + return nil, err + } + + // Since the asset is AVAX, we divide by the avaxConversionRate to + // convert back to the correct denomination of AVAX that can be + // exported. + avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() + + // If the balance for [addr] is insufficient to cover the additional + // cost of adding an input to the transaction, skip adding the input + // altogether. + if avaxBalance <= additionalFee { + continue + } + + // Update the cost for the next iteration + cost = newCost + + amountToConsume, err = math.Add64(amountToConsume, additionalFee) + if err != nil { + return nil, err + } + + nonce, err := b.backend.Nonce(ctx, addr) + if err != nil { + return nil, err + } + + inputAmount := math.Min(amountToConsume, avaxBalance) + inputs = append(inputs, evm.EVMInput{ + Address: addr, + Amount: inputAmount, + AssetID: avaxAssetID, + Nonce: nonce, + }) + amountToConsume -= inputAmount + } + + if amountToConsume > 0 { + return nil, errInsufficientFunds + } + + utils.Sort(inputs) + tx.Ins = inputs + return tx, nil +} + +func getSpendableAmount( + utxo *avax.UTXO, + addrs set.Set[ids.ShortID], + minIssuanceTime uint64, + avaxAssetID ids.ID, +) (uint64, []uint32, bool) { + if utxo.Asset.ID != avaxAssetID { + // Only AVAX can be imported + return 0, nil, false + } + + out, ok := utxo.Out.(*secp256k1fx.TransferOutput) + if !ok { + // Can't import an unknown transfer output type + return 0, nil, false + } + + inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) + return out.Amt, inputSigIndices, ok +} diff --git a/wallet/chain/c/builder_with_options.go b/wallet/chain/c/builder_with_options.go index 9b7ab8399484..8416dddf9928 100644 --- a/wallet/chain/c/builder_with_options.go +++ b/wallet/chain/c/builder_with_options.go @@ -3,81 +3,81 @@ package c -// import ( -// "math/big" +import ( + "math/big" -// "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/coreth/plugin/evm" -// ethcommon "github.com/ethereum/go-ethereum/common" + ethcommon "github.com/ethereum/go-ethereum/common" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) -// var _ Builder = (*builderWithOptions)(nil) +var _ Builder = (*builderWithOptions)(nil) -// type builderWithOptions struct { -// Builder -// options []common.Option -// } +type builderWithOptions struct { + Builder + options []common.Option +} -// // NewBuilderWithOptions returns a new transaction builder that will use the -// // given options by default. -// // -// // - [builder] is the builder that will be called to perform the underlying -// // operations. -// // - [options] will be provided to the builder in addition to the options -// // provided in the method calls. -// func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { -// return &builderWithOptions{ -// Builder: builder, -// options: options, -// } -// } +// NewBuilderWithOptions returns a new transaction builder that will use the +// given options by default. +// +// - [builder] is the builder that will be called to perform the underlying +// operations. +// - [options] will be provided to the builder in addition to the options +// provided in the method calls. +func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { + return &builderWithOptions{ + Builder: builder, + options: options, + } +} -// func (b *builderWithOptions) GetBalance( -// options ...common.Option, -// ) (*big.Int, error) { -// return b.Builder.GetBalance( -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) GetBalance( + options ...common.Option, +) (*big.Int, error) { + return b.Builder.GetBalance( + common.UnionOptions(b.options, options)..., + ) +} -// func (b *builderWithOptions) GetImportableBalance( -// chainID ids.ID, -// options ...common.Option, -// ) (uint64, error) { -// return b.Builder.GetImportableBalance( -// chainID, -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) GetImportableBalance( + chainID ids.ID, + options ...common.Option, +) (uint64, error) { + return b.Builder.GetImportableBalance( + chainID, + common.UnionOptions(b.options, options)..., + ) +} -// func (b *builderWithOptions) NewImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedImportTx, error) { -// return b.Builder.NewImportTx( -// chainID, -// to, -// baseFee, -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) NewImportTx( + chainID ids.ID, + to ethcommon.Address, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedImportTx, error) { + return b.Builder.NewImportTx( + chainID, + to, + baseFee, + common.UnionOptions(b.options, options)..., + ) +} -// func (b *builderWithOptions) NewExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedExportTx, error) { -// return b.Builder.NewExportTx( -// chainID, -// outputs, -// baseFee, -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) NewExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedExportTx, error) { + return b.Builder.NewExportTx( + chainID, + outputs, + baseFee, + common.UnionOptions(b.options, options)..., + ) +} diff --git a/wallet/chain/c/context.go b/wallet/chain/c/context.go index 1c01d8fb55c8..d506b42f81fa 100644 --- a/wallet/chain/c/context.go +++ b/wallet/chain/c/context.go @@ -3,81 +3,81 @@ package c -// import ( -// stdcontext "context" +import ( + stdcontext "context" -// "github.com/ava-labs/avalanchego/api/info" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/avm" -// ) + "github.com/ava-labs/avalanchego/api/info" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/avm" +) -// var _ Context = (*context)(nil) +var _ Context = (*context)(nil) -// type Context interface { -// NetworkID() uint32 -// BlockchainID() ids.ID -// AVAXAssetID() ids.ID -// } +type Context interface { + NetworkID() uint32 + BlockchainID() ids.ID + AVAXAssetID() ids.ID +} -// type context struct { -// networkID uint32 -// blockchainID ids.ID -// avaxAssetID ids.ID -// } +type context struct { + networkID uint32 + blockchainID ids.ID + avaxAssetID ids.ID +} -// func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { -// infoClient := info.NewClient(uri) -// xChainClient := avm.NewClient(uri, "X") -// return NewContextFromClients(ctx, infoClient, xChainClient) -// } +func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { + infoClient := info.NewClient(uri) + xChainClient := avm.NewClient(uri, "X") + return NewContextFromClients(ctx, infoClient, xChainClient) +} -// func NewContextFromClients( -// ctx stdcontext.Context, -// infoClient info.Client, -// xChainClient avm.Client, -// ) (Context, error) { -// networkID, err := infoClient.GetNetworkID(ctx) -// if err != nil { -// return nil, err -// } +func NewContextFromClients( + ctx stdcontext.Context, + infoClient info.Client, + xChainClient avm.Client, +) (Context, error) { + networkID, err := infoClient.GetNetworkID(ctx) + if err != nil { + return nil, err + } -// chainID, err := infoClient.GetBlockchainID(ctx, "C") -// if err != nil { -// return nil, err -// } + chainID, err := infoClient.GetBlockchainID(ctx, "C") + if err != nil { + return nil, err + } -// asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") -// if err != nil { -// return nil, err -// } + asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") + if err != nil { + return nil, err + } -// return NewContext( -// networkID, -// chainID, -// asset.AssetID, -// ), nil -// } + return NewContext( + networkID, + chainID, + asset.AssetID, + ), nil +} -// func NewContext( -// networkID uint32, -// blockchainID ids.ID, -// avaxAssetID ids.ID, -// ) Context { -// return &context{ -// networkID: networkID, -// blockchainID: blockchainID, -// avaxAssetID: avaxAssetID, -// } -// } +func NewContext( + networkID uint32, + blockchainID ids.ID, + avaxAssetID ids.ID, +) Context { + return &context{ + networkID: networkID, + blockchainID: blockchainID, + avaxAssetID: avaxAssetID, + } +} -// func (c *context) NetworkID() uint32 { -// return c.networkID -// } +func (c *context) NetworkID() uint32 { + return c.networkID +} -// func (c *context) BlockchainID() ids.ID { -// return c.blockchainID -// } +func (c *context) BlockchainID() ids.ID { + return c.blockchainID +} -// func (c *context) AVAXAssetID() ids.ID { -// return c.avaxAssetID -// } +func (c *context) AVAXAssetID() ids.ID { + return c.avaxAssetID +} diff --git a/wallet/chain/c/signer.go b/wallet/chain/c/signer.go index 4bedc378234b..4fd85ed3b532 100644 --- a/wallet/chain/c/signer.go +++ b/wallet/chain/c/signer.go @@ -3,221 +3,221 @@ package c -// import ( -// "errors" -// "fmt" - -// stdcontext "context" - -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/database" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils/crypto/keychain" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/hashing" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/components/verify" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// ) - -// const version = 0 - -// var ( -// _ Signer = (*txSigner)(nil) - -// errUnknownInputType = errors.New("unknown input type") -// errUnknownCredentialType = errors.New("unknown credential type") -// errUnknownOutputType = errors.New("unknown output type") -// errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") - -// emptySig [secp256k1.SignatureLen]byte -// ) - -// type Signer interface { -// SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) -// SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error -// } - -// type EthKeychain interface { -// // The returned Signer can provide a signature for [addr] -// GetEth(addr ethcommon.Address) (keychain.Signer, bool) -// // Returns the set of addresses for which the accessor keeps an associated -// // signer -// EthAddresses() set.Set[ethcommon.Address] -// } - -// type SignerBackend interface { -// GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) -// } - -// type txSigner struct { -// avaxKC keychain.Keychain -// ethKC EthKeychain -// backend SignerBackend -// } - -// func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { -// return &txSigner{ -// avaxKC: avaxKC, -// ethKC: ethKC, -// backend: backend, -// } -// } - -// func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { -// tx := &evm.Tx{UnsignedAtomicTx: utx} -// return tx, s.SignAtomic(ctx, tx) -// } - -// func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { -// switch utx := tx.UnsignedAtomicTx.(type) { -// case *evm.UnsignedImportTx: -// signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) -// if err != nil { -// return err -// } -// return sign(tx, true, signers) -// case *evm.UnsignedExportTx: -// signers := s.getExportSigners(utx.Ins) -// return sign(tx, true, signers) -// default: -// return fmt.Errorf("%w: %T", errUnknownTxType, tx) -// } -// } - -// func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { -// txSigners := make([][]keychain.Signer, len(ins)) -// for credIndex, transferInput := range ins { -// input, ok := transferInput.In.(*secp256k1fx.TransferInput) -// if !ok { -// return nil, errUnknownInputType -// } - -// inputSigners := make([]keychain.Signer, len(input.SigIndices)) -// txSigners[credIndex] = inputSigners - -// utxoID := transferInput.InputID() -// utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) -// if err == database.ErrNotFound { -// // If we don't have access to the UTXO, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// if err != nil { -// return nil, err -// } - -// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) -// if !ok { -// return nil, errUnknownOutputType -// } - -// for sigIndex, addrIndex := range input.SigIndices { -// if addrIndex >= uint32(len(out.Addrs)) { -// return nil, errInvalidUTXOSigIndex -// } - -// addr := out.Addrs[addrIndex] -// key, ok := s.avaxKC.Get(addr) -// if !ok { -// // If we don't have access to the key, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// inputSigners[sigIndex] = key -// } -// } -// return txSigners, nil -// } - -// func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { -// txSigners := make([][]keychain.Signer, len(ins)) -// for credIndex, input := range ins { -// inputSigners := make([]keychain.Signer, 1) -// txSigners[credIndex] = inputSigners - -// key, ok := s.ethKC.GetEth(input.Address) -// if !ok { -// // If we don't have access to the key, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// inputSigners[0] = key -// } -// return txSigners -// } - -// // TODO: remove [signHash] after the ledger supports signing all transactions. -// func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { -// unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) -// if err != nil { -// return fmt.Errorf("couldn't marshal unsigned tx: %w", err) -// } -// unsignedHash := hashing.ComputeHash256(unsignedBytes) - -// if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { -// tx.Creds = make([]verify.Verifiable, expectedLen) -// } - -// sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) -// for credIndex, inputSigners := range txSigners { -// credIntf := tx.Creds[credIndex] -// if credIntf == nil { -// credIntf = &secp256k1fx.Credential{} -// tx.Creds[credIndex] = credIntf -// } - -// cred, ok := credIntf.(*secp256k1fx.Credential) -// if !ok { -// return errUnknownCredentialType -// } -// if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { -// cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) -// } - -// for sigIndex, signer := range inputSigners { -// if signer == nil { -// // If we don't have access to the key, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// addr := signer.Address() -// if sig := cred.Sigs[sigIndex]; sig != emptySig { -// // If this signature has already been populated, we can just -// // copy the needed signature for the future. -// sigCache[addr] = sig -// continue -// } - -// if sig, exists := sigCache[addr]; exists { -// // If this key has already produced a signature, we can just -// // copy the previous signature. -// cred.Sigs[sigIndex] = sig -// continue -// } - -// var sig []byte -// if signHash { -// sig, err = signer.SignHash(unsignedHash) -// } else { -// sig, err = signer.Sign(unsignedBytes) -// } -// if err != nil { -// return fmt.Errorf("problem signing tx: %w", err) -// } -// copy(cred.Sigs[sigIndex][:], sig) -// sigCache[addr] = cred.Sigs[sigIndex] -// } -// } - -// signedBytes, err := evm.Codec.Marshal(version, tx) -// if err != nil { -// return fmt.Errorf("couldn't marshal tx: %w", err) -// } -// tx.Initialize(unsignedBytes, signedBytes) -// return nil -// } +import ( + "errors" + "fmt" + + stdcontext "context" + + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/crypto/keychain" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/hashing" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/components/verify" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" +) + +const version = 0 + +var ( + _ Signer = (*txSigner)(nil) + + errUnknownInputType = errors.New("unknown input type") + errUnknownCredentialType = errors.New("unknown credential type") + errUnknownOutputType = errors.New("unknown output type") + errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") + + emptySig [secp256k1.SignatureLen]byte +) + +type Signer interface { + SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) + SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error +} + +type EthKeychain interface { + // The returned Signer can provide a signature for [addr] + GetEth(addr ethcommon.Address) (keychain.Signer, bool) + // Returns the set of addresses for which the accessor keeps an associated + // signer + EthAddresses() set.Set[ethcommon.Address] +} + +type SignerBackend interface { + GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) +} + +type txSigner struct { + avaxKC keychain.Keychain + ethKC EthKeychain + backend SignerBackend +} + +func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { + return &txSigner{ + avaxKC: avaxKC, + ethKC: ethKC, + backend: backend, + } +} + +func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { + tx := &evm.Tx{UnsignedAtomicTx: utx} + return tx, s.SignAtomic(ctx, tx) +} + +func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { + switch utx := tx.UnsignedAtomicTx.(type) { + case *evm.UnsignedImportTx: + signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) + if err != nil { + return err + } + return sign(tx, true, signers) + case *evm.UnsignedExportTx: + signers := s.getExportSigners(utx.Ins) + return sign(tx, true, signers) + default: + return fmt.Errorf("%w: %T", errUnknownTxType, tx) + } +} + +func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { + txSigners := make([][]keychain.Signer, len(ins)) + for credIndex, transferInput := range ins { + input, ok := transferInput.In.(*secp256k1fx.TransferInput) + if !ok { + return nil, errUnknownInputType + } + + inputSigners := make([]keychain.Signer, len(input.SigIndices)) + txSigners[credIndex] = inputSigners + + utxoID := transferInput.InputID() + utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) + if err == database.ErrNotFound { + // If we don't have access to the UTXO, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + if err != nil { + return nil, err + } + + out, ok := utxo.Out.(*secp256k1fx.TransferOutput) + if !ok { + return nil, errUnknownOutputType + } + + for sigIndex, addrIndex := range input.SigIndices { + if addrIndex >= uint32(len(out.Addrs)) { + return nil, errInvalidUTXOSigIndex + } + + addr := out.Addrs[addrIndex] + key, ok := s.avaxKC.Get(addr) + if !ok { + // If we don't have access to the key, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + inputSigners[sigIndex] = key + } + } + return txSigners, nil +} + +func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { + txSigners := make([][]keychain.Signer, len(ins)) + for credIndex, input := range ins { + inputSigners := make([]keychain.Signer, 1) + txSigners[credIndex] = inputSigners + + key, ok := s.ethKC.GetEth(input.Address) + if !ok { + // If we don't have access to the key, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + inputSigners[0] = key + } + return txSigners +} + +// TODO: remove [signHash] after the ledger supports signing all transactions. +func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { + unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) + if err != nil { + return fmt.Errorf("couldn't marshal unsigned tx: %w", err) + } + unsignedHash := hashing.ComputeHash256(unsignedBytes) + + if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { + tx.Creds = make([]verify.Verifiable, expectedLen) + } + + sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) + for credIndex, inputSigners := range txSigners { + credIntf := tx.Creds[credIndex] + if credIntf == nil { + credIntf = &secp256k1fx.Credential{} + tx.Creds[credIndex] = credIntf + } + + cred, ok := credIntf.(*secp256k1fx.Credential) + if !ok { + return errUnknownCredentialType + } + if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { + cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) + } + + for sigIndex, signer := range inputSigners { + if signer == nil { + // If we don't have access to the key, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + addr := signer.Address() + if sig := cred.Sigs[sigIndex]; sig != emptySig { + // If this signature has already been populated, we can just + // copy the needed signature for the future. + sigCache[addr] = sig + continue + } + + if sig, exists := sigCache[addr]; exists { + // If this key has already produced a signature, we can just + // copy the previous signature. + cred.Sigs[sigIndex] = sig + continue + } + + var sig []byte + if signHash { + sig, err = signer.SignHash(unsignedHash) + } else { + sig, err = signer.Sign(unsignedBytes) + } + if err != nil { + return fmt.Errorf("problem signing tx: %w", err) + } + copy(cred.Sigs[sigIndex][:], sig) + sigCache[addr] = cred.Sigs[sigIndex] + } + } + + signedBytes, err := evm.Codec.Marshal(version, tx) + if err != nil { + return fmt.Errorf("couldn't marshal tx: %w", err) + } + tx.Initialize(unsignedBytes, signedBytes) + return nil +} diff --git a/wallet/chain/c/wallet.go b/wallet/chain/c/wallet.go index ebee50a9a958..fb1a83d53dad 100644 --- a/wallet/chain/c/wallet.go +++ b/wallet/chain/c/wallet.go @@ -3,204 +3,204 @@ package c -// import ( -// "errors" -// "math/big" -// "time" - -// "github.com/ava-labs/coreth/ethclient" -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var ( -// _ Wallet = (*wallet)(nil) - -// errNotCommitted = errors.New("not committed") -// ) - -// type Wallet interface { -// Context - -// // Builder returns the builder that will be used to create the transactions. -// Builder() Builder - -// // Signer returns the signer that will be used to sign the transactions. -// Signer() Signer - -// // IssueImportTx creates, signs, and issues an import transaction that -// // attempts to consume all the available UTXOs and import the funds to [to]. -// // -// // - [chainID] specifies the chain to be importing funds from. -// // - [to] specifies where to send the imported funds to. -// IssueImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// options ...common.Option, -// ) (*evm.Tx, error) - -// // IssueExportTx creates, signs, and issues an export transaction that -// // attempts to send all the provided [outputs] to the requested [chainID]. -// // -// // - [chainID] specifies the chain to be exporting the funds to. -// // - [outputs] specifies the outputs to send to the [chainID]. -// IssueExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// options ...common.Option, -// ) (*evm.Tx, error) - -// // IssueUnsignedTx signs and issues the unsigned tx. -// IssueUnsignedAtomicTx( -// utx evm.UnsignedAtomicTx, -// options ...common.Option, -// ) (*evm.Tx, error) - -// // IssueAtomicTx issues the signed tx. -// IssueAtomicTx( -// tx *evm.Tx, -// options ...common.Option, -// ) error -// } - -// func NewWallet( -// builder Builder, -// signer Signer, -// avaxClient evm.Client, -// ethClient ethclient.Client, -// backend Backend, -// ) Wallet { -// return &wallet{ -// Backend: backend, -// builder: builder, -// signer: signer, -// avaxClient: avaxClient, -// ethClient: ethClient, -// } -// } - -// type wallet struct { -// Backend -// builder Builder -// signer Signer -// avaxClient evm.Client -// ethClient ethclient.Client -// } - -// func (w *wallet) Builder() Builder { -// return w.builder -// } - -// func (w *wallet) Signer() Signer { -// return w.signer -// } - -// func (w *wallet) IssueImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// options ...common.Option, -// ) (*evm.Tx, error) { -// baseFee, err := w.baseFee(options) -// if err != nil { -// return nil, err -// } - -// utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) -// if err != nil { -// return nil, err -// } -// return w.IssueUnsignedAtomicTx(utx, options...) -// } - -// func (w *wallet) IssueExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// options ...common.Option, -// ) (*evm.Tx, error) { -// baseFee, err := w.baseFee(options) -// if err != nil { -// return nil, err -// } - -// utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) -// if err != nil { -// return nil, err -// } -// return w.IssueUnsignedAtomicTx(utx, options...) -// } - -// func (w *wallet) IssueUnsignedAtomicTx( -// utx evm.UnsignedAtomicTx, -// options ...common.Option, -// ) (*evm.Tx, error) { -// ops := common.NewOptions(options) -// ctx := ops.Context() -// tx, err := w.signer.SignUnsignedAtomic(ctx, utx) -// if err != nil { -// return nil, err -// } - -// return tx, w.IssueAtomicTx(tx, options...) -// } - -// func (w *wallet) IssueAtomicTx( -// tx *evm.Tx, -// options ...common.Option, -// ) error { -// ops := common.NewOptions(options) -// ctx := ops.Context() -// txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) -// if err != nil { -// return err -// } - -// if f := ops.PostIssuanceFunc(); f != nil { -// f(txID) -// } - -// if ops.AssumeDecided() { -// return w.Backend.AcceptAtomicTx(ctx, tx) -// } - -// pollFrequency := ops.PollFrequency() -// ticker := time.NewTicker(pollFrequency) -// defer ticker.Stop() - -// for { -// status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) -// if err != nil { -// return err -// } - -// switch status { -// case evm.Accepted: -// return w.Backend.AcceptAtomicTx(ctx, tx) -// case evm.Dropped, evm.Unknown: -// return errNotCommitted -// } - -// // The tx is Processing. - -// select { -// case <-ticker.C: -// case <-ctx.Done(): -// return ctx.Err() -// } -// } -// } - -// func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { -// ops := common.NewOptions(options) -// baseFee := ops.BaseFee(nil) -// if baseFee != nil { -// return baseFee, nil -// } - -// ctx := ops.Context() -// return w.ethClient.EstimateBaseFee(ctx) -// } +import ( + "errors" + "math/big" + "time" + + "github.com/ava-labs/coreth/ethclient" + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var ( + _ Wallet = (*wallet)(nil) + + errNotCommitted = errors.New("not committed") +) + +type Wallet interface { + Context + + // Builder returns the builder that will be used to create the transactions. + Builder() Builder + + // Signer returns the signer that will be used to sign the transactions. + Signer() Signer + + // IssueImportTx creates, signs, and issues an import transaction that + // attempts to consume all the available UTXOs and import the funds to [to]. + // + // - [chainID] specifies the chain to be importing funds from. + // - [to] specifies where to send the imported funds to. + IssueImportTx( + chainID ids.ID, + to ethcommon.Address, + options ...common.Option, + ) (*evm.Tx, error) + + // IssueExportTx creates, signs, and issues an export transaction that + // attempts to send all the provided [outputs] to the requested [chainID]. + // + // - [chainID] specifies the chain to be exporting the funds to. + // - [outputs] specifies the outputs to send to the [chainID]. + IssueExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + options ...common.Option, + ) (*evm.Tx, error) + + // IssueUnsignedTx signs and issues the unsigned tx. + IssueUnsignedAtomicTx( + utx evm.UnsignedAtomicTx, + options ...common.Option, + ) (*evm.Tx, error) + + // IssueAtomicTx issues the signed tx. + IssueAtomicTx( + tx *evm.Tx, + options ...common.Option, + ) error +} + +func NewWallet( + builder Builder, + signer Signer, + avaxClient evm.Client, + ethClient ethclient.Client, + backend Backend, +) Wallet { + return &wallet{ + Backend: backend, + builder: builder, + signer: signer, + avaxClient: avaxClient, + ethClient: ethClient, + } +} + +type wallet struct { + Backend + builder Builder + signer Signer + avaxClient evm.Client + ethClient ethclient.Client +} + +func (w *wallet) Builder() Builder { + return w.builder +} + +func (w *wallet) Signer() Signer { + return w.signer +} + +func (w *wallet) IssueImportTx( + chainID ids.ID, + to ethcommon.Address, + options ...common.Option, +) (*evm.Tx, error) { + baseFee, err := w.baseFee(options) + if err != nil { + return nil, err + } + + utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) + if err != nil { + return nil, err + } + return w.IssueUnsignedAtomicTx(utx, options...) +} + +func (w *wallet) IssueExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + options ...common.Option, +) (*evm.Tx, error) { + baseFee, err := w.baseFee(options) + if err != nil { + return nil, err + } + + utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) + if err != nil { + return nil, err + } + return w.IssueUnsignedAtomicTx(utx, options...) +} + +func (w *wallet) IssueUnsignedAtomicTx( + utx evm.UnsignedAtomicTx, + options ...common.Option, +) (*evm.Tx, error) { + ops := common.NewOptions(options) + ctx := ops.Context() + tx, err := w.signer.SignUnsignedAtomic(ctx, utx) + if err != nil { + return nil, err + } + + return tx, w.IssueAtomicTx(tx, options...) +} + +func (w *wallet) IssueAtomicTx( + tx *evm.Tx, + options ...common.Option, +) error { + ops := common.NewOptions(options) + ctx := ops.Context() + txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) + if err != nil { + return err + } + + if f := ops.PostIssuanceFunc(); f != nil { + f(txID) + } + + if ops.AssumeDecided() { + return w.Backend.AcceptAtomicTx(ctx, tx) + } + + pollFrequency := ops.PollFrequency() + ticker := time.NewTicker(pollFrequency) + defer ticker.Stop() + + for { + status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) + if err != nil { + return err + } + + switch status { + case evm.Accepted: + return w.Backend.AcceptAtomicTx(ctx, tx) + case evm.Dropped, evm.Unknown: + return errNotCommitted + } + + // The tx is Processing. + + select { + case <-ticker.C: + case <-ctx.Done(): + return ctx.Err() + } + } +} + +func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { + ops := common.NewOptions(options) + baseFee := ops.BaseFee(nil) + if baseFee != nil { + return baseFee, nil + } + + ctx := ops.Context() + return w.ethClient.EstimateBaseFee(ctx) +} diff --git a/wallet/chain/c/wallet_with_options.go b/wallet/chain/c/wallet_with_options.go index fd69a6d4fd02..7d6193683d49 100644 --- a/wallet/chain/c/wallet_with_options.go +++ b/wallet/chain/c/wallet_with_options.go @@ -3,80 +3,80 @@ package c -// import ( -// "github.com/ava-labs/coreth/plugin/evm" +import ( + "github.com/ava-labs/coreth/plugin/evm" -// ethcommon "github.com/ethereum/go-ethereum/common" + ethcommon "github.com/ethereum/go-ethereum/common" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) -// var _ Wallet = (*walletWithOptions)(nil) +var _ Wallet = (*walletWithOptions)(nil) -// func NewWalletWithOptions( -// wallet Wallet, -// options ...common.Option, -// ) Wallet { -// return &walletWithOptions{ -// Wallet: wallet, -// options: options, -// } -// } +func NewWalletWithOptions( + wallet Wallet, + options ...common.Option, +) Wallet { + return &walletWithOptions{ + Wallet: wallet, + options: options, + } +} -// type walletWithOptions struct { -// Wallet -// options []common.Option -// } +type walletWithOptions struct { + Wallet + options []common.Option +} -// func (w *walletWithOptions) Builder() Builder { -// return NewBuilderWithOptions( -// w.Wallet.Builder(), -// w.options..., -// ) -// } +func (w *walletWithOptions) Builder() Builder { + return NewBuilderWithOptions( + w.Wallet.Builder(), + w.options..., + ) +} -// func (w *walletWithOptions) IssueImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// options ...common.Option, -// ) (*evm.Tx, error) { -// return w.Wallet.IssueImportTx( -// chainID, -// to, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueImportTx( + chainID ids.ID, + to ethcommon.Address, + options ...common.Option, +) (*evm.Tx, error) { + return w.Wallet.IssueImportTx( + chainID, + to, + common.UnionOptions(w.options, options)..., + ) +} -// func (w *walletWithOptions) IssueExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// options ...common.Option, -// ) (*evm.Tx, error) { -// return w.Wallet.IssueExportTx( -// chainID, -// outputs, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + options ...common.Option, +) (*evm.Tx, error) { + return w.Wallet.IssueExportTx( + chainID, + outputs, + common.UnionOptions(w.options, options)..., + ) +} -// func (w *walletWithOptions) IssueUnsignedAtomicTx( -// utx evm.UnsignedAtomicTx, -// options ...common.Option, -// ) (*evm.Tx, error) { -// return w.Wallet.IssueUnsignedAtomicTx( -// utx, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueUnsignedAtomicTx( + utx evm.UnsignedAtomicTx, + options ...common.Option, +) (*evm.Tx, error) { + return w.Wallet.IssueUnsignedAtomicTx( + utx, + common.UnionOptions(w.options, options)..., + ) +} -// func (w *walletWithOptions) IssueAtomicTx( -// tx *evm.Tx, -// options ...common.Option, -// ) error { -// return w.Wallet.IssueAtomicTx( -// tx, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueAtomicTx( + tx *evm.Tx, + options ...common.Option, +) error { + return w.Wallet.IssueAtomicTx( + tx, + common.UnionOptions(w.options, options)..., + ) +} diff --git a/wallet/subnet/primary/api.go b/wallet/subnet/primary/api.go index 3260c05a0a1b..3ac72c217884 100644 --- a/wallet/subnet/primary/api.go +++ b/wallet/subnet/primary/api.go @@ -5,6 +5,12 @@ package primary import ( "context" + "fmt" + + "github.com/ava-labs/coreth/ethclient" + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ethereum/go-ethereum/common" "github.com/ava-labs/avalanchego/api/info" "github.com/ava-labs/avalanchego/codec" @@ -16,6 +22,7 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm" "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" ) @@ -52,9 +59,9 @@ type AVAXState struct { PCTX p.Context XClient avm.Client XCTX x.Context - // CClient evm.Client - // CCTX c.Context - UTXOs UTXOs + CClient evm.Client + CCTX c.Context + UTXOs UTXOs } func FetchState( @@ -68,7 +75,7 @@ func FetchState( infoClient := info.NewClient(uri) pClient := platformvm.NewClient(uri) xClient := avm.NewClient(uri, "X") - // cClient := evm.NewCChainClient(uri) + cClient := evm.NewCChainClient(uri) pCTX, err := p.NewContextFromClients(ctx, infoClient, xClient) if err != nil { @@ -80,10 +87,10 @@ func FetchState( return nil, err } - // cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) - // if err != nil { - // return nil, err - // } + cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) + if err != nil { + return nil, err + } utxos := NewUTXOs() addrList := addrs.List() @@ -102,11 +109,11 @@ func FetchState( client: xClient, codec: x.Parser.Codec(), }, - // { - // id: cCTX.BlockchainID(), - // client: cClient, - // codec: evm.Codec, - // }, + { + id: cCTX.BlockchainID(), + client: cClient, + codec: evm.Codec, + }, } for _, destinationChain := range chains { for _, sourceChain := range chains { @@ -129,52 +136,52 @@ func FetchState( PCTX: pCTX, XClient: xClient, XCTX: xCTX, - // CClient: cClient, - // CCTX: cCTX, - UTXOs: utxos, + CClient: cClient, + CCTX: cCTX, + UTXOs: utxos, }, nil } -// type EthState struct { -// Client ethclient.Client -// Accounts map[common.Address]*c.Account -// } - -// func FetchEthState( -// ctx context.Context, -// uri string, -// addrs set.Set[common.Address], -// ) (*EthState, error) { -// path := fmt.Sprintf( -// "%s/ext/%s/C/rpc", -// uri, -// constants.ChainAliasPrefix, -// ) -// client, err := ethclient.Dial(path) -// if err != nil { -// return nil, err -// } - -// accounts := make(map[common.Address]*c.Account, addrs.Len()) -// for addr := range addrs { -// balance, err := client.BalanceAt(ctx, addr, nil) -// if err != nil { -// return nil, err -// } -// nonce, err := client.NonceAt(ctx, addr, nil) -// if err != nil { -// return nil, err -// } -// accounts[addr] = &c.Account{ -// Balance: balance, -// Nonce: nonce, -// } -// } -// return &EthState{ -// Client: client, -// Accounts: accounts, -// }, nil -// } +type EthState struct { + Client ethclient.Client + Accounts map[common.Address]*c.Account +} + +func FetchEthState( + ctx context.Context, + uri string, + addrs set.Set[common.Address], +) (*EthState, error) { + path := fmt.Sprintf( + "%s/ext/%s/C/rpc", + uri, + constants.ChainAliasPrefix, + ) + client, err := ethclient.Dial(path) + if err != nil { + return nil, err + } + + accounts := make(map[common.Address]*c.Account, addrs.Len()) + for addr := range addrs { + balance, err := client.BalanceAt(ctx, addr, nil) + if err != nil { + return nil, err + } + nonce, err := client.NonceAt(ctx, addr, nil) + if err != nil { + return nil, err + } + accounts[addr] = &c.Account{ + Balance: balance, + Nonce: nonce, + } + } + return &EthState{ + Client: client, + Accounts: accounts, + }, nil +} // AddAllUTXOs fetches all the UTXOs referenced by [addresses] that were sent // from [sourceChainID] to [destinationChainID] from the [client]. It then uses diff --git a/wallet/subnet/primary/example_test.go b/wallet/subnet/primary/example_test.go index 4a73e8c070b2..483c049d4ac0 100644 --- a/wallet/subnet/primary/example_test.go +++ b/wallet/subnet/primary/example_test.go @@ -30,7 +30,7 @@ func ExampleWallet() { wallet, err := MakeWallet(ctx, &WalletConfig{ URI: LocalAPIURI, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet with: %s\n", err) diff --git a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go index 21c081d2982b..d5e8ce422307 100644 --- a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go @@ -46,9 +46,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/add-primary-validator/main.go b/wallet/subnet/primary/examples/add-primary-validator/main.go index 13c28f995f63..a56dae23db3a 100644 --- a/wallet/subnet/primary/examples/add-primary-validator/main.go +++ b/wallet/subnet/primary/examples/add-primary-validator/main.go @@ -45,7 +45,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/c-chain-export/main.go b/wallet/subnet/primary/examples/c-chain-export/main.go index a6b9a0c810b8..fec55c899feb 100644 --- a/wallet/subnet/primary/examples/c-chain-export/main.go +++ b/wallet/subnet/primary/examples/c-chain-export/main.go @@ -3,70 +3,70 @@ package main -// import ( -// "context" -// "log" -// "time" +import ( + "context" + "log" + "time" -// "github.com/ava-labs/avalanchego/genesis" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary" -// ) + "github.com/ava-labs/avalanchego/genesis" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary" +) -// func main() { -// key := genesis.EWOQKey -// uri := primary.LocalAPIURI -// kc := secp256k1fx.NewKeychain(key) -// avaxAddr := key.Address() +func main() { + key := genesis.EWOQKey + uri := primary.LocalAPIURI + kc := secp256k1fx.NewKeychain(key) + avaxAddr := key.Address() -// ctx := context.Background() + ctx := context.Background() -// // MakeWallet fetches the available UTXOs owned by [kc] on the network that -// // [uri] is hosting. -// walletSyncStartTime := time.Now() -// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ -// URI: uri, -// AVAXKeychain: kc, -// EthKeychain: kc, -// }) -// if err != nil { -// log.Fatalf("failed to initialize wallet: %s\n", err) -// } -// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) + // MakeWallet fetches the available UTXOs owned by [kc] on the network that + // [uri] is hosting. + walletSyncStartTime := time.Now() + wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, + }) + if err != nil { + log.Fatalf("failed to initialize wallet: %s\n", err) + } + log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) -// // Get the P-chain wallet -// pWallet := wallet.P() -// cWallet := wallet.C() + // Get the P-chain wallet + pWallet := wallet.P() + cWallet := wallet.C() -// // Pull out useful constants to use when issuing transactions. -// cChainID := cWallet.BlockchainID() -// owner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// avaxAddr, -// }, -// } + // Pull out useful constants to use when issuing transactions. + cChainID := cWallet.BlockchainID() + owner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + avaxAddr, + }, + } -// exportStartTime := time.Now() -// exportTx, err := cWallet.IssueExportTx( -// constants.PlatformChainID, -// []*secp256k1fx.TransferOutput{{ -// Amt: units.Avax, -// OutputOwners: owner, -// }}, -// ) -// if err != nil { -// log.Fatalf("failed to issue export transaction: %s\n", err) -// } -// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) + exportStartTime := time.Now() + exportTx, err := cWallet.IssueExportTx( + constants.PlatformChainID, + []*secp256k1fx.TransferOutput{{ + Amt: units.Avax, + OutputOwners: owner, + }}, + ) + if err != nil { + log.Fatalf("failed to issue export transaction: %s\n", err) + } + log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) -// importStartTime := time.Now() -// importTx, err := pWallet.IssueImportTx(cChainID, &owner) -// if err != nil { -// log.Fatalf("failed to issue import transaction: %s\n", err) -// } -// log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) -// } + importStartTime := time.Now() + importTx, err := pWallet.IssueImportTx(cChainID, &owner) + if err != nil { + log.Fatalf("failed to issue import transaction: %s\n", err) + } + log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) +} diff --git a/wallet/subnet/primary/examples/c-chain-import/main.go b/wallet/subnet/primary/examples/c-chain-import/main.go index 2d9b8a244cb0..b4dc4e603eb3 100644 --- a/wallet/subnet/primary/examples/c-chain-import/main.go +++ b/wallet/subnet/primary/examples/c-chain-import/main.go @@ -3,75 +3,75 @@ package main -// import ( -// "context" -// "log" -// "time" +import ( + "context" + "log" + "time" -// "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/coreth/plugin/evm" -// "github.com/ava-labs/avalanchego/genesis" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary" -// ) + "github.com/ava-labs/avalanchego/genesis" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary" +) -// func main() { -// key := genesis.EWOQKey -// uri := primary.LocalAPIURI -// kc := secp256k1fx.NewKeychain(key) -// avaxAddr := key.Address() -// ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) +func main() { + key := genesis.EWOQKey + uri := primary.LocalAPIURI + kc := secp256k1fx.NewKeychain(key) + avaxAddr := key.Address() + ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) -// ctx := context.Background() + ctx := context.Background() -// // MakeWallet fetches the available UTXOs owned by [kc] on the network that -// // [uri] is hosting. -// walletSyncStartTime := time.Now() -// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ -// URI: uri, -// AVAXKeychain: kc, -// EthKeychain: kc, -// }) -// if err != nil { -// log.Fatalf("failed to initialize wallet: %s\n", err) -// } -// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) + // MakeWallet fetches the available UTXOs owned by [kc] on the network that + // [uri] is hosting. + walletSyncStartTime := time.Now() + wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, + }) + if err != nil { + log.Fatalf("failed to initialize wallet: %s\n", err) + } + log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) -// // Get the P-chain wallet -// pWallet := wallet.P() -// cWallet := wallet.C() + // Get the P-chain wallet + pWallet := wallet.P() + cWallet := wallet.C() -// // Pull out useful constants to use when issuing transactions. -// cChainID := cWallet.BlockchainID() -// avaxAssetID := cWallet.AVAXAssetID() -// owner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// avaxAddr, -// }, -// } + // Pull out useful constants to use when issuing transactions. + cChainID := cWallet.BlockchainID() + avaxAssetID := cWallet.AVAXAssetID() + owner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + avaxAddr, + }, + } -// exportStartTime := time.Now() -// exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ -// Asset: avax.Asset{ID: avaxAssetID}, -// Out: &secp256k1fx.TransferOutput{ -// Amt: units.Avax, -// OutputOwners: owner, -// }, -// }}) -// if err != nil { -// log.Fatalf("failed to issue export transaction: %s\n", err) -// } -// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) + exportStartTime := time.Now() + exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ + Asset: avax.Asset{ID: avaxAssetID}, + Out: &secp256k1fx.TransferOutput{ + Amt: units.Avax, + OutputOwners: owner, + }, + }}) + if err != nil { + log.Fatalf("failed to issue export transaction: %s\n", err) + } + log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) -// importStartTime := time.Now() -// importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) -// if err != nil { -// log.Fatalf("failed to issue import transaction: %s\n", err) -// } -// log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) -// } + importStartTime := time.Now() + importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) + if err != nil { + log.Fatalf("failed to issue import transaction: %s\n", err) + } + log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) +} diff --git a/wallet/subnet/primary/examples/create-asset/main.go b/wallet/subnet/primary/examples/create-asset/main.go index 0bccfbb5fc52..30804f083df6 100644 --- a/wallet/subnet/primary/examples/create-asset/main.go +++ b/wallet/subnet/primary/examples/create-asset/main.go @@ -30,7 +30,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-chain/main.go b/wallet/subnet/primary/examples/create-chain/main.go index 521a3cca53cf..5e6898a1b649 100644 --- a/wallet/subnet/primary/examples/create-chain/main.go +++ b/wallet/subnet/primary/examples/create-chain/main.go @@ -41,9 +41,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/create-locked-stakeable/main.go b/wallet/subnet/primary/examples/create-locked-stakeable/main.go index 92f1b5cb0e1b..e688968e9e8a 100644 --- a/wallet/subnet/primary/examples/create-locked-stakeable/main.go +++ b/wallet/subnet/primary/examples/create-locked-stakeable/main.go @@ -39,7 +39,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-subnet/main.go b/wallet/subnet/primary/examples/create-subnet/main.go index 3e8d69bc016a..add98ea7931c 100644 --- a/wallet/subnet/primary/examples/create-subnet/main.go +++ b/wallet/subnet/primary/examples/create-subnet/main.go @@ -28,7 +28,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/remove-subnet-validator/main.go b/wallet/subnet/primary/examples/remove-subnet-validator/main.go index 46f4b85124db..2842c7c0a790 100644 --- a/wallet/subnet/primary/examples/remove-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/remove-subnet-validator/main.go @@ -38,9 +38,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/wallet.go b/wallet/subnet/primary/wallet.go index de50d12f866b..54de390d029c 100644 --- a/wallet/subnet/primary/wallet.go +++ b/wallet/subnet/primary/wallet.go @@ -11,6 +11,7 @@ import ( "github.com/ava-labs/avalanchego/utils/crypto/keychain" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" @@ -22,13 +23,13 @@ var _ Wallet = (*wallet)(nil) type Wallet interface { P() p.Wallet X() x.Wallet - // C() c.Wallet + C() c.Wallet } type wallet struct { p p.Wallet x x.Wallet - // c c.Wallet + c c.Wallet } func (w *wallet) P() p.Wallet { @@ -39,16 +40,16 @@ func (w *wallet) X() x.Wallet { return w.x } -// func (w *wallet) C() c.Wallet { -// return w.c -// } +func (w *wallet) C() c.Wallet { + return w.c +} // Creates a new default wallet -func NewWallet(p p.Wallet, x x.Wallet /*, c c.Wallet*/) Wallet { +func NewWallet(p p.Wallet, x x.Wallet, c c.Wallet) Wallet { return &wallet{ p: p, x: x, - // c: c, + c: c, } } @@ -57,7 +58,7 @@ func NewWalletWithOptions(w Wallet, options ...common.Option) Wallet { return NewWallet( p.NewWalletWithOptions(w.P(), options...), x.NewWalletWithOptions(w.X(), options...), - // c.NewWalletWithOptions(w.C(), options...), + c.NewWalletWithOptions(w.C(), options...), ) } @@ -66,7 +67,7 @@ type WalletConfig struct { URI string // required // Keys to use for signing all transactions. AVAXKeychain keychain.Keychain // required - // EthKeychain c.EthKeychain // required + EthKeychain c.EthKeychain // required // Set of P-chain transactions that the wallet should know about to be able // to generate transactions. PChainTxs map[ids.ID]*txs.Tx // optional @@ -92,11 +93,11 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { return nil, err } - // ethAddrs := config.EthKeychain.EthAddresses() - // ethState, err := FetchEthState(ctx, config.URI, ethAddrs) - // if err != nil { - // return nil, err - // } + ethAddrs := config.EthKeychain.EthAddresses() + ethState, err := FetchEthState(ctx, config.URI, ethAddrs) + if err != nil { + return nil, err + } pChainTxs := config.PChainTxs if pChainTxs == nil { @@ -126,15 +127,15 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { xBuilder := x.NewBuilder(avaxAddrs, xBackend) xSigner := x.NewSigner(config.AVAXKeychain, xBackend) - // cChainID := avaxState.CCTX.BlockchainID() - // cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) - // cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) - // cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) - // cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) + cChainID := avaxState.CCTX.BlockchainID() + cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) + cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) + cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) + cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) return NewWallet( p.NewWallet(pBuilder, pSigner, avaxState.PClient, pBackend), x.NewWallet(xBuilder, xSigner, avaxState.XClient, xBackend), - // c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), + c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), ), nil } From 0c70a78a8966b10b11326fe335bb6fa251eeb89b Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 2 Nov 2023 19:16:48 +0100 Subject: [PATCH 27/36] temporarily cut coreth dependencies --- go.mod | 25 - go.sum | 76 -- node/node.go | 4 +- tests/e2e/c/dynamic_fees.go | 326 +++---- tests/e2e/c/interchain_workflow.go | 320 +++---- tests/e2e/e2e.go | 116 ++- tests/e2e/p/interchain_workflow.go | 444 +++++----- tests/e2e/x/interchain_workflow.go | 296 +++---- tests/fixture/testnet/config.go | 54 +- vms/example/xsvm/cmd/chain/create/cmd.go | 6 +- wallet/chain/c/backend.go | 300 +++---- wallet/chain/c/builder.go | 792 +++++++++--------- wallet/chain/c/builder_with_options.go | 136 +-- wallet/chain/c/context.go | 130 +-- wallet/chain/c/signer.go | 436 +++++----- wallet/chain/c/wallet.go | 402 ++++----- wallet/chain/c/wallet_with_options.go | 134 +-- wallet/subnet/primary/api.go | 119 ++- wallet/subnet/primary/example_test.go | 2 +- .../add-permissioned-subnet-validator/main.go | 6 +- .../examples/add-primary-validator/main.go | 2 +- .../primary/examples/c-chain-export/main.go | 118 +-- .../primary/examples/c-chain-import/main.go | 126 +-- .../primary/examples/create-asset/main.go | 2 +- .../primary/examples/create-chain/main.go | 6 +- .../examples/create-locked-stakeable/main.go | 2 +- .../primary/examples/create-subnet/main.go | 2 +- .../examples/remove-subnet-validator/main.go | 6 +- wallet/subnet/primary/wallet.go | 41 +- 29 files changed, 2154 insertions(+), 2275 deletions(-) diff --git a/go.mod b/go.mod index 3117c0edf3e1..40d59d0cb294 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,6 @@ require ( github.com/DataDog/zstd v1.5.2 github.com/Microsoft/go-winio v0.5.2 github.com/NYTimes/gziphandler v1.1.1 - github.com/ava-labs/coreth v0.12.8-rc.1 github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 github.com/btcsuite/btcd/btcutil v1.1.3 github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 @@ -72,7 +71,6 @@ require ( require ( github.com/BurntSushi/toml v1.2.1 // indirect - github.com/VictoriaMetrics/fastcache v1.10.0 // indirect github.com/benbjohnson/clock v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect @@ -81,44 +79,26 @@ require ( github.com/cockroachdb/errors v1.9.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/redact v1.1.3 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/deckarep/golang-set/v2 v2.1.0 // indirect - github.com/dlclark/regexp2 v1.7.0 // indirect - github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect - github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/frankban/quicktest v1.14.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect - github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect - github.com/go-stack/stack v1.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect - github.com/google/uuid v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 // indirect - github.com/hashicorp/go-bexpr v0.1.10 // indirect - github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/klauspost/compress v1.15.15 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/magiconair/properties v1.8.6 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/mitchellh/pointerstructure v1.2.0 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect @@ -126,17 +106,12 @@ require ( github.com/prometheus/common v0.39.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sanity-io/litter v1.5.1 // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/status-im/keycard-go v0.2.0 // indirect github.com/subosito/gotenv v1.3.0 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect - github.com/tyler-smith/go-bip39 v1.1.0 // indirect - github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa // indirect - github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/zondax/hid v0.9.1 // indirect github.com/zondax/ledger-go v0.14.1 // indirect diff --git a/go.sum b/go.sum index 0ad1313cd1b7..09e5526b3f20 100644 --- a/go.sum +++ b/go.sum @@ -52,18 +52,12 @@ github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cq github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= -github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY= -github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/ava-labs/coreth v0.12.8-rc.1 h1:tvJcxQTQzxIQqx8TnrxdyMhZYbdsMaiy6AEiOyjvaa4= -github.com/ava-labs/coreth v0.12.8-rc.1/go.mod h1:GBH5SxHZdScSp95IijDs9+Gxw/QDIWvfoLKiJMNYLsE= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 h1:EdxD90j5sClfL5Ngpz2TlnbnkNYdFPDXa0jDOjam65c= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7/go.mod h1:XhiXSrh90sHUbkERzaxEftCmUz53eCijshDLZ4fByVM= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= @@ -100,18 +94,13 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -141,16 +130,12 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= -github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= @@ -161,14 +146,6 @@ github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6ps github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= -github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= -github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= -github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= -github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -185,8 +162,6 @@ github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2 github.com/ethereum/go-ethereum v1.12.0/go.mod h1:/oo2X/dZLJjf2mJ6YT9wcWxa4nNJDBKDBU6sFIpx1Gs= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -195,8 +170,6 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= @@ -220,11 +193,7 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= -github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= @@ -309,14 +278,10 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -337,17 +302,11 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 h1:kr3j8iIMR4ywO/O0rvksXaJvauGGCMg2zAZIiNZ9uIQ= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0/go.mod h1:ummNFgdgLhhX7aIiy35vVmQNS0rWXknfPE0qe6fmFXg= -github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= -github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e/go.mod h1:j9cQbcqHQujT0oKJ38PylVfqohClLr3CvDC+Qcg+lhU= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8= @@ -359,7 +318,6 @@ github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3 github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -401,7 +359,6 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -409,7 +366,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= @@ -420,17 +376,11 @@ github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -439,11 +389,8 @@ github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= -github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -462,8 +409,6 @@ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -531,8 +476,6 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sanity-io/litter v1.5.1 h1:dwnrSypP6q56o3lFxTU+t2fwQ9A+U5qrXVO4Qg9KwVU= github.com/sanity-io/litter v1.5.1/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0= @@ -568,8 +511,6 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= -github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= -github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -599,14 +540,10 @@ github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITn github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= -github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -618,8 +555,6 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1: github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= @@ -629,7 +564,6 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= @@ -727,7 +661,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -773,7 +706,6 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -797,7 +729,6 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -862,12 +793,8 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -884,7 +811,6 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -948,7 +874,6 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1073,7 +998,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= diff --git a/node/node.go b/node/node.go index cad0073899b8..f12d591d5ccf 100644 --- a/node/node.go +++ b/node/node.go @@ -25,7 +25,7 @@ import ( "go.uber.org/zap" - coreth "github.com/ava-labs/coreth/plugin/evm" + // coreth "github.com/ava-labs/coreth/plugin/evm" "github.com/ava-labs/avalanchego/api/admin" "github.com/ava-labs/avalanchego/api/auth" @@ -940,7 +940,7 @@ func (n *Node) initVMs() error { CreateAssetTxFee: n.Config.CreateAssetTxFee, }, }), - vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), + // vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), n.VMManager.RegisterFactory(context.TODO(), secp256k1fx.ID, &secp256k1fx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), nftfx.ID, &nftfx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), propertyfx.ID, &propertyfx.Factory{}), diff --git a/tests/e2e/c/dynamic_fees.go b/tests/e2e/c/dynamic_fees.go index edfbef2671a8..779c8670be37 100644 --- a/tests/e2e/c/dynamic_fees.go +++ b/tests/e2e/c/dynamic_fees.go @@ -3,166 +3,166 @@ package c -import ( - "math/big" - "strings" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/stretchr/testify/require" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/coreth/core/types" - "github.com/ava-labs/coreth/params" - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/tests" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/tests/fixture/testnet" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -) - -// This test uses the compiled bin for `hashing.sol` as -// well as its ABI contained in `hashing_contract.go`. - -var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { - require := require.New(ginkgo.GinkgoT()) - - // Need a gas limit much larger than the standard 21_000 to enable - // the contract to induce a gas price increase - const largeGasLimit = uint64(8_000_000) - - // TODO(marun) What is the significance of this value? - gasTip := big.NewInt(1000 * params.GWei) - - ginkgo.It("should ensure that the gas price is affected by load", func() { - ginkgo.By("creating a new private network to ensure isolation from other tests") - privateNetwork := e2e.Env.NewPrivateNetwork() - - ginkgo.By("allocating a pre-funded key") - key := privateNetwork.GetConfig().FundedKeys[0] - ethAddress := evm.GetEthAddress(key) - - ginkgo.By("initializing a coreth client") - node := privateNetwork.GetNodes()[0] - nodeURI := testnet.NodeURI{ - NodeID: node.GetID(), - URI: node.GetProcessContext().URI, - } - ethClient := e2e.Env.NewEthClient(nodeURI) - - ginkgo.By("initializing a transaction signer") - cChainID, err := ethClient.ChainID(e2e.DefaultContext()) - require.NoError(err) - signer := types.NewEIP155Signer(cChainID) - ecdsaKey := key.ToECDSA() - sign := func(tx *types.Transaction) *types.Transaction { - signedTx, err := types.SignTx(tx, signer, ecdsaKey) - require.NoError(err) - return signedTx - } - - var contractAddress common.Address - ginkgo.By("deploying an expensive contract", func() { - // Create transaction - nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) - require.NoError(err) - compiledContract := common.Hex2Bytes(hashingCompiledContract) - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - GasPrice: gasTip, - Gas: largeGasLimit, - Value: common.Big0, - Data: compiledContract, - }) - - // Send the transaction and wait for acceptance - signedTx := sign(tx) - receipt := e2e.SendEthTransaction(ethClient, signedTx) - - contractAddress = receipt.ContractAddress - }) - - var gasPrice *big.Int - ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { - // Evaluate the bytes representation of the contract - hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) - require.NoError(err) - contractData, err := hashingABI.Pack("hashIt") - require.NoError(err) - - var initialGasPrice *big.Int - e2e.Eventually(func() bool { - // Check the gas price - var err error - gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) - require.NoError(err) - if initialGasPrice == nil { - initialGasPrice = gasPrice - tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) - } else if gasPrice.Cmp(initialGasPrice) > 0 { - // Gas price has increased - tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) - return true - } - - // Create the transaction - nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) - require.NoError(err) - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - GasPrice: gasTip, - Gas: largeGasLimit, - To: &contractAddress, - Value: common.Big0, - Data: contractData, - }) - - // Send the transaction and wait for acceptance - signedTx := sign(tx) - _ = e2e.SendEthTransaction(ethClient, signedTx) - - // The gas price will be checked at the start of the next iteration - return false - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") - }) - - ginkgo.By("waiting for the gas price to decrease...", func() { - initialGasPrice := gasPrice - e2e.Eventually(func() bool { - var err error - gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) - require.NoError(err) - tests.Outf("{{blue}}.{{/}}") - return initialGasPrice.Cmp(gasPrice) > 0 - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") - tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) - }) - - ginkgo.By("sending funds at the current gas price", func() { - // Create a recipient address - recipientKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - recipientEthAddress := evm.GetEthAddress(recipientKey) - - // Create transaction - nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) - require.NoError(err) - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - GasPrice: gasPrice, - Gas: e2e.DefaultGasLimit, - To: &recipientEthAddress, - Value: common.Big0, - }) - - // Send the transaction and wait for acceptance - signedTx := sign(tx) - _ = e2e.SendEthTransaction(ethClient, signedTx) - }) - - e2e.CheckBootstrapIsPossible(privateNetwork) - }) -}) +// import ( +// "math/big" +// "strings" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/stretchr/testify/require" + +// "github.com/ethereum/go-ethereum/accounts/abi" +// "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/coreth/core/types" +// "github.com/ava-labs/coreth/params" +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/tests" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/tests/fixture/testnet" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// ) + +// // This test uses the compiled bin for `hashing.sol` as +// // well as its ABI contained in `hashing_contract.go`. + +// var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { +// require := require.New(ginkgo.GinkgoT()) + +// // Need a gas limit much larger than the standard 21_000 to enable +// // the contract to induce a gas price increase +// const largeGasLimit = uint64(8_000_000) + +// // TODO(marun) What is the significance of this value? +// gasTip := big.NewInt(1000 * params.GWei) + +// ginkgo.It("should ensure that the gas price is affected by load", func() { +// ginkgo.By("creating a new private network to ensure isolation from other tests") +// privateNetwork := e2e.Env.NewPrivateNetwork() + +// ginkgo.By("allocating a pre-funded key") +// key := privateNetwork.GetConfig().FundedKeys[0] +// ethAddress := evm.GetEthAddress(key) + +// ginkgo.By("initializing a coreth client") +// node := privateNetwork.GetNodes()[0] +// nodeURI := testnet.NodeURI{ +// NodeID: node.GetID(), +// URI: node.GetProcessContext().URI, +// } +// ethClient := e2e.Env.NewEthClient(nodeURI) + +// ginkgo.By("initializing a transaction signer") +// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) +// require.NoError(err) +// signer := types.NewEIP155Signer(cChainID) +// ecdsaKey := key.ToECDSA() +// sign := func(tx *types.Transaction) *types.Transaction { +// signedTx, err := types.SignTx(tx, signer, ecdsaKey) +// require.NoError(err) +// return signedTx +// } + +// var contractAddress common.Address +// ginkgo.By("deploying an expensive contract", func() { +// // Create transaction +// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) +// require.NoError(err) +// compiledContract := common.Hex2Bytes(hashingCompiledContract) +// tx := types.NewTx(&types.LegacyTx{ +// Nonce: nonce, +// GasPrice: gasTip, +// Gas: largeGasLimit, +// Value: common.Big0, +// Data: compiledContract, +// }) + +// // Send the transaction and wait for acceptance +// signedTx := sign(tx) +// receipt := e2e.SendEthTransaction(ethClient, signedTx) + +// contractAddress = receipt.ContractAddress +// }) + +// var gasPrice *big.Int +// ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { +// // Evaluate the bytes representation of the contract +// hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) +// require.NoError(err) +// contractData, err := hashingABI.Pack("hashIt") +// require.NoError(err) + +// var initialGasPrice *big.Int +// e2e.Eventually(func() bool { +// // Check the gas price +// var err error +// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) +// require.NoError(err) +// if initialGasPrice == nil { +// initialGasPrice = gasPrice +// tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) +// } else if gasPrice.Cmp(initialGasPrice) > 0 { +// // Gas price has increased +// tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) +// return true +// } + +// // Create the transaction +// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) +// require.NoError(err) +// tx := types.NewTx(&types.LegacyTx{ +// Nonce: nonce, +// GasPrice: gasTip, +// Gas: largeGasLimit, +// To: &contractAddress, +// Value: common.Big0, +// Data: contractData, +// }) + +// // Send the transaction and wait for acceptance +// signedTx := sign(tx) +// _ = e2e.SendEthTransaction(ethClient, signedTx) + +// // The gas price will be checked at the start of the next iteration +// return false +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") +// }) + +// ginkgo.By("waiting for the gas price to decrease...", func() { +// initialGasPrice := gasPrice +// e2e.Eventually(func() bool { +// var err error +// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) +// require.NoError(err) +// tests.Outf("{{blue}}.{{/}}") +// return initialGasPrice.Cmp(gasPrice) > 0 +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") +// tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) +// }) + +// ginkgo.By("sending funds at the current gas price", func() { +// // Create a recipient address +// recipientKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) +// recipientEthAddress := evm.GetEthAddress(recipientKey) + +// // Create transaction +// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) +// require.NoError(err) +// tx := types.NewTx(&types.LegacyTx{ +// Nonce: nonce, +// GasPrice: gasPrice, +// Gas: e2e.DefaultGasLimit, +// To: &recipientEthAddress, +// Value: common.Big0, +// }) + +// // Send the transaction and wait for acceptance +// signedTx := sign(tx) +// _ = e2e.SendEthTransaction(ethClient, signedTx) +// }) + +// e2e.CheckBootstrapIsPossible(privateNetwork) +// }) +// }) diff --git a/tests/e2e/c/interchain_workflow.go b/tests/e2e/c/interchain_workflow.go index 8bed85eb1bd9..d13c4b8db1ce 100644 --- a/tests/e2e/c/interchain_workflow.go +++ b/tests/e2e/c/interchain_workflow.go @@ -3,163 +3,163 @@ package c -import ( - "math/big" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/coreth/core/types" - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { - require := require.New(ginkgo.GinkgoT()) - - const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer - - ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { - ginkgo.By("initializing a new eth client") - // Select a random node URI to use for both the eth client and - // the wallet to avoid having to verify that all nodes are at - // the same height before initializing the wallet. - nodeURI := e2e.Env.GetRandomNodeURI() - ethClient := e2e.Env.NewEthClient(nodeURI) - - ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") - senderKey := e2e.Env.AllocateFundedKey() - senderEthAddress := evm.GetEthAddress(senderKey) - recipientKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - recipientEthAddress := evm.GetEthAddress(recipientKey) - - ginkgo.By("sending funds from one address to another on the C-Chain", func() { - // Create transaction - acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) - require.NoError(err) - gasPrice := e2e.SuggestGasPrice(ethClient) - tx := types.NewTransaction( - acceptedNonce, - recipientEthAddress, - big.NewInt(int64(txAmount)), - e2e.DefaultGasLimit, - gasPrice, - nil, - ) - - // Sign transaction - cChainID, err := ethClient.ChainID(e2e.DefaultContext()) - require.NoError(err) - signer := types.NewEIP155Signer(cChainID) - signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) - require.NoError(err) - - _ = e2e.SendEthTransaction(ethClient, signedTx) - - ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") - e2e.Eventually(func() bool { - balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) - require.NoError(err) - return balance.Cmp(big.NewInt(0)) > 0 - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") - }) - - // Wallet must be initialized after sending funds on the - // C-Chain with the same node URI to ensure wallet state - // matches on-chain state. - ginkgo.By("initializing a keychain and associated wallet") - keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) - baseWallet := e2e.Env.NewWallet(keychain, nodeURI) - xWallet := baseWallet.X() - cWallet := baseWallet.C() - pWallet := baseWallet.P() - - ginkgo.By("defining common configuration") - avaxAssetID := xWallet.AVAXAssetID() - // Use the same owner for import funds to X-Chain and P-Chain - recipientOwner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - recipientKey.Address(), - }, - } - // Use the same outputs for both X-Chain and P-Chain exports - exportOutputs := []*secp256k1fx.TransferOutput{ - { - Amt: txAmount, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - keychain.Keys[0].Address(), - }, - }, - }, - } - - ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { - _, err := cWallet.IssueExportTx( - xWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { - _, err := xWallet.IssueImportTx( - cWallet.BlockchainID(), - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { - balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { - _, err := cWallet.IssueExportTx( - constants.PlatformChainID, - exportOutputs, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { - _, err = pWallet.IssueImportTx( - cWallet.BlockchainID(), - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { - balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) - }) -}) +// import ( +// "math/big" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/stretchr/testify/require" + +// "github.com/ava-labs/coreth/core/types" +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { +// require := require.New(ginkgo.GinkgoT()) + +// const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer + +// ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { +// ginkgo.By("initializing a new eth client") +// // Select a random node URI to use for both the eth client and +// // the wallet to avoid having to verify that all nodes are at +// // the same height before initializing the wallet. +// nodeURI := e2e.Env.GetRandomNodeURI() +// ethClient := e2e.Env.NewEthClient(nodeURI) + +// ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") +// senderKey := e2e.Env.AllocateFundedKey() +// senderEthAddress := evm.GetEthAddress(senderKey) +// recipientKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) +// recipientEthAddress := evm.GetEthAddress(recipientKey) + +// ginkgo.By("sending funds from one address to another on the C-Chain", func() { +// // Create transaction +// acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) +// require.NoError(err) +// gasPrice := e2e.SuggestGasPrice(ethClient) +// tx := types.NewTransaction( +// acceptedNonce, +// recipientEthAddress, +// big.NewInt(int64(txAmount)), +// e2e.DefaultGasLimit, +// gasPrice, +// nil, +// ) + +// // Sign transaction +// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) +// require.NoError(err) +// signer := types.NewEIP155Signer(cChainID) +// signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) +// require.NoError(err) + +// _ = e2e.SendEthTransaction(ethClient, signedTx) + +// ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") +// e2e.Eventually(func() bool { +// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) +// require.NoError(err) +// return balance.Cmp(big.NewInt(0)) > 0 +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") +// }) + +// // Wallet must be initialized after sending funds on the +// // C-Chain with the same node URI to ensure wallet state +// // matches on-chain state. +// ginkgo.By("initializing a keychain and associated wallet") +// keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) +// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) +// xWallet := baseWallet.X() +// cWallet := baseWallet.C() +// pWallet := baseWallet.P() + +// ginkgo.By("defining common configuration") +// avaxAssetID := xWallet.AVAXAssetID() +// // Use the same owner for import funds to X-Chain and P-Chain +// recipientOwner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// recipientKey.Address(), +// }, +// } +// // Use the same outputs for both X-Chain and P-Chain exports +// exportOutputs := []*secp256k1fx.TransferOutput{ +// { +// Amt: txAmount, +// OutputOwners: secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// keychain.Keys[0].Address(), +// }, +// }, +// }, +// } + +// ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { +// _, err := cWallet.IssueExportTx( +// xWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { +// _, err := xWallet.IssueImportTx( +// cWallet.BlockchainID(), +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { +// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { +// _, err := cWallet.IssueExportTx( +// constants.PlatformChainID, +// exportOutputs, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { +// _, err = pWallet.IssueImportTx( +// cWallet.BlockchainID(), +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { +// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) +// }) +// }) diff --git a/tests/e2e/e2e.go b/tests/e2e/e2e.go index 130f33f1197c..8b70b9f9ca3f 100644 --- a/tests/e2e/e2e.go +++ b/tests/e2e/e2e.go @@ -7,23 +7,15 @@ package e2e import ( "context" "encoding/json" - "errors" - "fmt" - "math/big" "math/rand" "os" "path/filepath" - "strings" "time" ginkgo "github.com/onsi/ginkgo/v2" "github.com/stretchr/testify/require" - "github.com/ava-labs/coreth/core/types" - "github.com/ava-labs/coreth/ethclient" - "github.com/ava-labs/coreth/interfaces" - "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/tests" "github.com/ava-labs/avalanchego/tests/fixture" @@ -134,7 +126,7 @@ func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain, nodeURI tes baseWallet, err := primary.MakeWallet(DefaultContext(), &primary.WalletConfig{ URI: nodeURI.URI, AVAXKeychain: keychain, - EthKeychain: keychain, + // EthKeychain: keychain, }) te.require.NoError(err) return primary.NewWalletWithOptions( @@ -147,16 +139,16 @@ func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain, nodeURI tes ) } -// Create a new eth client targeting the specified node URI. -// TODO(marun) Make this a regular function. -func (te *TestEnvironment) NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { - tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) - nodeAddress := strings.Split(nodeURI.URI, "//")[1] - uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) - client, err := ethclient.Dial(uri) - te.require.NoError(err) - return client -} +// // Create a new eth client targeting the specified node URI. +// // TODO(marun) Make this a regular function. +// func (te *TestEnvironment) NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { +// tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) +// nodeAddress := strings.Split(nodeURI.URI, "//")[1] +// uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) +// client, err := ethclient.Dial(uri) +// te.require.NoError(err) +// return client +// } // Create a new private network that is not shared with other tests. func (te *TestEnvironment) NewPrivateNetwork() testnet.Network { @@ -231,49 +223,49 @@ func WaitForHealthy(node testnet.Node) { require.NoError(ginkgo.GinkgoT(), testnet.WaitForHealthy(DefaultContext(), node)) } -// Sends an eth transaction, waits for the transaction receipt to be issued -// and checks that the receipt indicates success. -func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { - require := require.New(ginkgo.GinkgoT()) - - txID := signedTx.Hash() - tests.Outf(" sending eth transaction with ID: %s\n", txID) - - require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) - - // Wait for the receipt - var receipt *types.Receipt - Eventually(func() bool { - var err error - receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) - if errors.Is(err, interfaces.NotFound) { - return false // Transaction is still pending - } - require.NoError(err) - return true - }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") - - require.Equal(receipt.Status, types.ReceiptStatusSuccessful) - return receipt -} - -// Determines the suggested gas price for the configured client that will -// maximize the chances of transaction acceptance. -func SuggestGasPrice(ethClient ethclient.Client) *big.Int { - gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) - require.NoError(ginkgo.GinkgoT(), err) - // Double the suggested gas price to maximize the chances of - // acceptance. Maybe this can be revisited pending resolution of - // https://github.com/ava-labs/coreth/issues/314. - gasPrice.Add(gasPrice, gasPrice) - return gasPrice -} - -// Helper simplifying use via an option of a gas price appropriate for testing. -func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { - baseFee := SuggestGasPrice(ethClient) - return common.WithBaseFee(baseFee) -} +// // Sends an eth transaction, waits for the transaction receipt to be issued +// // and checks that the receipt indicates success. +// func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { +// require := require.New(ginkgo.GinkgoT()) + +// txID := signedTx.Hash() +// tests.Outf(" sending eth transaction with ID: %s\n", txID) + +// require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) + +// // Wait for the receipt +// var receipt *types.Receipt +// Eventually(func() bool { +// var err error +// receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) +// if errors.Is(err, interfaces.NotFound) { +// return false // Transaction is still pending +// } +// require.NoError(err) +// return true +// }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") + +// require.Equal(receipt.Status, types.ReceiptStatusSuccessful) +// return receipt +// } + +// // Determines the suggested gas price for the configured client that will +// // maximize the chances of transaction acceptance. +// func SuggestGasPrice(ethClient ethclient.Client) *big.Int { +// gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) +// require.NoError(ginkgo.GinkgoT(), err) +// // Double the suggested gas price to maximize the chances of +// // acceptance. Maybe this can be revisited pending resolution of +// // https://github.com/ava-labs/coreth/issues/314. +// gasPrice.Add(gasPrice, gasPrice) +// return gasPrice +// } + +// // Helper simplifying use via an option of a gas price appropriate for testing. +// func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { +// baseFee := SuggestGasPrice(ethClient) +// return common.WithBaseFee(baseFee) +// } // Verify that a new node can bootstrap into the network. func CheckBootstrapIsPossible(network testnet.Network) { diff --git a/tests/e2e/p/interchain_workflow.go b/tests/e2e/p/interchain_workflow.go index 729418adbd97..d3715c254e90 100644 --- a/tests/e2e/p/interchain_workflow.go +++ b/tests/e2e/p/interchain_workflow.go @@ -3,225 +3,225 @@ package p -import ( - "math/big" - "time" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/spf13/cast" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/api/info" - "github.com/ava-labs/avalanchego/config" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/tests/fixture/testnet" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/platformvm/reward" - "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { - require := require.New(ginkgo.GinkgoT()) - - const ( - transferAmount = 10 * units.Avax - weight = 2_000 * units.Avax // Used for both validation and delegation - ) - - ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { - network := e2e.Env.GetNetwork() - - ginkgo.By("checking that the network has a compatible minimum stake duration", func() { - minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) - require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) - }) - - ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") - recipientKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - keychain := e2e.Env.NewKeychain(1) - keychain.Add(recipientKey) - nodeURI := e2e.Env.GetRandomNodeURI() - baseWallet := e2e.Env.NewWallet(keychain, nodeURI) - xWallet := baseWallet.X() - cWallet := baseWallet.C() - pWallet := baseWallet.P() - - ginkgo.By("defining common configuration") - recipientEthAddress := evm.GetEthAddress(recipientKey) - avaxAssetID := xWallet.AVAXAssetID() - // Use the same owner for sending to X-Chain and importing funds to P-Chain - recipientOwner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - recipientKey.Address(), - }, - } - // Use the same outputs for both X-Chain and C-Chain exports - exportOutputs := []*avax.TransferableOutput{ - { - Asset: avax.Asset{ - ID: avaxAssetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: transferAmount, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - keychain.Keys[0].Address(), - }, - }, - }, - }, - } - - ginkgo.By("adding new node and waiting for it to report healthy") - node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) - e2e.WaitForHealthy(node) - - ginkgo.By("retrieving new node's id and pop") - infoClient := info.NewClient(node.GetProcessContext().URI) - nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) - require.NoError(err) - - ginkgo.By("adding the new node as a validator", func() { - startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) - // Validation duration doesn't actually matter to this - // test - it is only ensuring that adding a validator - // doesn't break interchain transfer. - endTime := startTime.Add(30 * time.Second) - - rewardKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - - const ( - delegationPercent = 0.10 // 10% - delegationShare = reward.PercentDenominator * delegationPercent - ) - - _, err = pWallet.IssueAddPermissionlessValidatorTx( - &txs.SubnetValidator{ - Validator: txs.Validator{ - NodeID: nodeID, - Start: uint64(startTime.Unix()), - End: uint64(endTime.Unix()), - Wght: weight, - }, - Subnet: constants.PrimaryNetworkID, - }, - nodePOP, - pWallet.AVAXAssetID(), - &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{rewardKey.Address()}, - }, - &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{rewardKey.Address()}, - }, - delegationShare, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("adding a delegator to the new node", func() { - startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) - // Delegation duration doesn't actually matter to this - // test - it is only ensuring that adding a delegator - // doesn't break interchain transfer. - endTime := startTime.Add(15 * time.Second) - - rewardKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - - _, err = pWallet.IssueAddPermissionlessDelegatorTx( - &txs.SubnetValidator{ - Validator: txs.Validator{ - NodeID: nodeID, - Start: uint64(startTime.Unix()), - End: uint64(endTime.Unix()), - Wght: weight, - }, - Subnet: constants.PrimaryNetworkID, - }, - pWallet.AVAXAssetID(), - &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{rewardKey.Address()}, - }, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { - _, err := pWallet.IssueExportTx( - xWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { - _, err := xWallet.IssueImportTx( - constants.PlatformChainID, - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { - balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { - _, err := pWallet.IssueExportTx( - cWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("initializing a new eth client") - ethClient := e2e.Env.NewEthClient(nodeURI) - - ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { - _, err := cWallet.IssueImportTx( - constants.PlatformChainID, - recipientEthAddress, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") - balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) - require.NoError(err) - require.Positive(balance.Cmp(big.NewInt(0))) - - ginkgo.By("stopping validator node to free up resources for a bootstrap check") - require.NoError(node.Stop()) - - e2e.CheckBootstrapIsPossible(network) - }) -}) +// import ( +// "math/big" +// "time" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/spf13/cast" + +// "github.com/stretchr/testify/require" + +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/api/info" +// "github.com/ava-labs/avalanchego/config" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/tests/fixture/testnet" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/platformvm/reward" +// "github.com/ava-labs/avalanchego/vms/platformvm/txs" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { +// require := require.New(ginkgo.GinkgoT()) + +// const ( +// transferAmount = 10 * units.Avax +// weight = 2_000 * units.Avax // Used for both validation and delegation +// ) + +// ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { +// network := e2e.Env.GetNetwork() + +// ginkgo.By("checking that the network has a compatible minimum stake duration", func() { +// minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) +// require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) +// }) + +// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") +// recipientKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) +// keychain := e2e.Env.NewKeychain(1) +// keychain.Add(recipientKey) +// nodeURI := e2e.Env.GetRandomNodeURI() +// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) +// xWallet := baseWallet.X() +// cWallet := baseWallet.C() +// pWallet := baseWallet.P() + +// ginkgo.By("defining common configuration") +// recipientEthAddress := evm.GetEthAddress(recipientKey) +// avaxAssetID := xWallet.AVAXAssetID() +// // Use the same owner for sending to X-Chain and importing funds to P-Chain +// recipientOwner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// recipientKey.Address(), +// }, +// } +// // Use the same outputs for both X-Chain and C-Chain exports +// exportOutputs := []*avax.TransferableOutput{ +// { +// Asset: avax.Asset{ +// ID: avaxAssetID, +// }, +// Out: &secp256k1fx.TransferOutput{ +// Amt: transferAmount, +// OutputOwners: secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// keychain.Keys[0].Address(), +// }, +// }, +// }, +// }, +// } + +// ginkgo.By("adding new node and waiting for it to report healthy") +// node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) +// e2e.WaitForHealthy(node) + +// ginkgo.By("retrieving new node's id and pop") +// infoClient := info.NewClient(node.GetProcessContext().URI) +// nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) +// require.NoError(err) + +// ginkgo.By("adding the new node as a validator", func() { +// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) +// // Validation duration doesn't actually matter to this +// // test - it is only ensuring that adding a validator +// // doesn't break interchain transfer. +// endTime := startTime.Add(30 * time.Second) + +// rewardKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) + +// const ( +// delegationPercent = 0.10 // 10% +// delegationShare = reward.PercentDenominator * delegationPercent +// ) + +// _, err = pWallet.IssueAddPermissionlessValidatorTx( +// &txs.SubnetValidator{ +// Validator: txs.Validator{ +// NodeID: nodeID, +// Start: uint64(startTime.Unix()), +// End: uint64(endTime.Unix()), +// Wght: weight, +// }, +// Subnet: constants.PrimaryNetworkID, +// }, +// nodePOP, +// pWallet.AVAXAssetID(), +// &secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{rewardKey.Address()}, +// }, +// &secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{rewardKey.Address()}, +// }, +// delegationShare, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("adding a delegator to the new node", func() { +// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) +// // Delegation duration doesn't actually matter to this +// // test - it is only ensuring that adding a delegator +// // doesn't break interchain transfer. +// endTime := startTime.Add(15 * time.Second) + +// rewardKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) + +// _, err = pWallet.IssueAddPermissionlessDelegatorTx( +// &txs.SubnetValidator{ +// Validator: txs.Validator{ +// NodeID: nodeID, +// Start: uint64(startTime.Unix()), +// End: uint64(endTime.Unix()), +// Wght: weight, +// }, +// Subnet: constants.PrimaryNetworkID, +// }, +// pWallet.AVAXAssetID(), +// &secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{rewardKey.Address()}, +// }, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { +// _, err := pWallet.IssueExportTx( +// xWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { +// _, err := xWallet.IssueImportTx( +// constants.PlatformChainID, +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { +// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { +// _, err := pWallet.IssueExportTx( +// cWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("initializing a new eth client") +// ethClient := e2e.Env.NewEthClient(nodeURI) + +// ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { +// _, err := cWallet.IssueImportTx( +// constants.PlatformChainID, +// recipientEthAddress, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") +// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) +// require.NoError(err) +// require.Positive(balance.Cmp(big.NewInt(0))) + +// ginkgo.By("stopping validator node to free up resources for a bootstrap check") +// require.NoError(node.Stop()) + +// e2e.CheckBootstrapIsPossible(network) +// }) +// }) diff --git a/tests/e2e/x/interchain_workflow.go b/tests/e2e/x/interchain_workflow.go index 6d335199b5b9..3b7a4c988405 100644 --- a/tests/e2e/x/interchain_workflow.go +++ b/tests/e2e/x/interchain_workflow.go @@ -3,151 +3,151 @@ package x -import ( - "math/big" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { - require := require.New(ginkgo.GinkgoT()) - - const transferAmount = 10 * units.Avax - - ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { - nodeURI := e2e.Env.GetRandomNodeURI() - - ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") - recipientKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - keychain := e2e.Env.NewKeychain(1) - keychain.Add(recipientKey) - baseWallet := e2e.Env.NewWallet(keychain, nodeURI) - xWallet := baseWallet.X() - cWallet := baseWallet.C() - pWallet := baseWallet.P() - - ginkgo.By("defining common configuration") - recipientEthAddress := evm.GetEthAddress(recipientKey) - avaxAssetID := xWallet.AVAXAssetID() - // Use the same owner for sending to X-Chain and importing funds to P-Chain - recipientOwner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - recipientKey.Address(), - }, - } - // Use the same outputs for both C-Chain and P-Chain exports - exportOutputs := []*avax.TransferableOutput{ - { - Asset: avax.Asset{ - ID: avaxAssetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: transferAmount, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - keychain.Keys[0].Address(), - }, - }, - }, - }, - } - - ginkgo.By("sending funds from one address to another on the X-Chain", func() { - _, err = xWallet.IssueBaseTx( - []*avax.TransferableOutput{{ - Asset: avax.Asset{ - ID: avaxAssetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: transferAmount, - OutputOwners: recipientOwner, - }, - }}, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { - balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { - _, err := xWallet.IssueExportTx( - cWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("initializing a new eth client") - ethClient := e2e.Env.NewEthClient(nodeURI) - - ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { - _, err := cWallet.IssueImportTx( - xWallet.BlockchainID(), - recipientEthAddress, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") - e2e.Eventually(func() bool { - balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) - require.NoError(err) - return balance.Cmp(big.NewInt(0)) > 0 - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") - - ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { - _, err := xWallet.IssueExportTx( - constants.PlatformChainID, - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { - _, err := pWallet.IssueImportTx( - xWallet.BlockchainID(), - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { - balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) - }) -}) +// import ( +// "math/big" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/stretchr/testify/require" + +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { +// require := require.New(ginkgo.GinkgoT()) + +// const transferAmount = 10 * units.Avax + +// ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { +// nodeURI := e2e.Env.GetRandomNodeURI() + +// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") +// recipientKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) +// keychain := e2e.Env.NewKeychain(1) +// keychain.Add(recipientKey) +// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) +// xWallet := baseWallet.X() +// cWallet := baseWallet.C() +// pWallet := baseWallet.P() + +// ginkgo.By("defining common configuration") +// recipientEthAddress := evm.GetEthAddress(recipientKey) +// avaxAssetID := xWallet.AVAXAssetID() +// // Use the same owner for sending to X-Chain and importing funds to P-Chain +// recipientOwner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// recipientKey.Address(), +// }, +// } +// // Use the same outputs for both C-Chain and P-Chain exports +// exportOutputs := []*avax.TransferableOutput{ +// { +// Asset: avax.Asset{ +// ID: avaxAssetID, +// }, +// Out: &secp256k1fx.TransferOutput{ +// Amt: transferAmount, +// OutputOwners: secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// keychain.Keys[0].Address(), +// }, +// }, +// }, +// }, +// } + +// ginkgo.By("sending funds from one address to another on the X-Chain", func() { +// _, err = xWallet.IssueBaseTx( +// []*avax.TransferableOutput{{ +// Asset: avax.Asset{ +// ID: avaxAssetID, +// }, +// Out: &secp256k1fx.TransferOutput{ +// Amt: transferAmount, +// OutputOwners: recipientOwner, +// }, +// }}, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { +// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { +// _, err := xWallet.IssueExportTx( +// cWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("initializing a new eth client") +// ethClient := e2e.Env.NewEthClient(nodeURI) + +// ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { +// _, err := cWallet.IssueImportTx( +// xWallet.BlockchainID(), +// recipientEthAddress, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") +// e2e.Eventually(func() bool { +// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) +// require.NoError(err) +// return balance.Cmp(big.NewInt(0)) > 0 +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") + +// ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { +// _, err := xWallet.IssueExportTx( +// constants.PlatformChainID, +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { +// _, err := pWallet.IssueImportTx( +// xWallet.BlockchainID(), +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { +// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) +// }) +// }) diff --git a/tests/fixture/testnet/config.go b/tests/fixture/testnet/config.go index 425aa646a690..6c82db1a420f 100644 --- a/tests/fixture/testnet/config.go +++ b/tests/fixture/testnet/config.go @@ -15,10 +15,6 @@ import ( "github.com/spf13/cast" - "github.com/ava-labs/coreth/core" - "github.com/ava-labs/coreth/params" - "github.com/ava-labs/coreth/plugin/evm" - "github.com/ava-labs/avalanchego/config" "github.com/ava-labs/avalanchego/genesis" "github.com/ava-labs/avalanchego/ids" @@ -143,15 +139,15 @@ func (c *NetworkConfig) EnsureGenesis(networkID uint32, validatorIDs []ids.NodeI // Ensure pre-funded keys have arbitrary large balances on both chains to support testing xChainBalances := make(XChainBalanceMap, len(c.FundedKeys)) - cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) - for _, key := range c.FundedKeys { - xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount - cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ - Balance: DefaultFundedKeyCChainAmount, - } - } - - genesis, err := NewTestGenesis(networkID, xChainBalances, cChainBalances, validatorIDs) + // cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) + // for _, key := range c.FundedKeys { + // xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount + // cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ + // Balance: DefaultFundedKeyCChainAmount, + // } + // } + + genesis, err := NewTestGenesis(networkID, xChainBalances /*, cChainBalances*/, validatorIDs) if err != nil { return err } @@ -311,7 +307,7 @@ type XChainBalanceMap map[ids.ShortID]uint64 func NewTestGenesis( networkID uint32, xChainBalances XChainBalanceMap, - cChainBalances core.GenesisAlloc, + // cChainBalances core.GenesisAlloc, validatorIDs []ids.NodeID, ) (*genesis.UnparsedConfig, error) { // Validate inputs @@ -322,7 +318,7 @@ func NewTestGenesis( if len(validatorIDs) == 0 { return nil, errMissingValidatorsForGenesis } - if len(xChainBalances) == 0 || len(cChainBalances) == 0 { + if len(xChainBalances) == 0 /*|| len(cChainBalances) == 0*/ { return nil, errMissingBalancesForGenesis } @@ -394,20 +390,20 @@ func NewTestGenesis( ) } - // Define C-Chain genesis - cChainGenesis := &core.Genesis{ - Config: ¶ms.ChainConfig{ - ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary - }, - Difficulty: big.NewInt(0), // Difficulty is a mandatory field - GasLimit: DefaultGasLimit, - Alloc: cChainBalances, - } - cChainGenesisBytes, err := json.Marshal(cChainGenesis) - if err != nil { - return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) - } - config.CChainGenesis = string(cChainGenesisBytes) + // // Define C-Chain genesis + // cChainGenesis := &core.Genesis{ + // Config: ¶ms.ChainConfig{ + // ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary + // }, + // Difficulty: big.NewInt(0), // Difficulty is a mandatory field + // GasLimit: DefaultGasLimit, + // Alloc: cChainBalances, + // } + // cChainGenesisBytes, err := json.Marshal(cChainGenesis) + // if err != nil { + // return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) + // } + // config.CChainGenesis = string(cChainGenesisBytes) // Give staking rewards for initial validators to a random address. Any testing of staking rewards // will be easier to perform with nodes other than the initial validators since the timing of diff --git a/vms/example/xsvm/cmd/chain/create/cmd.go b/vms/example/xsvm/cmd/chain/create/cmd.go index 1f00491a4ce6..043b4298dcdf 100644 --- a/vms/example/xsvm/cmd/chain/create/cmd.go +++ b/vms/example/xsvm/cmd/chain/create/cmd.go @@ -42,9 +42,9 @@ func createFunc(c *cobra.Command, args []string) error { // that [uri] is hosting. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: config.URI, - AVAXKeychain: kc, - EthKeychain: kc, + URI: config.URI, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(config.SubnetID), }) if err != nil { diff --git a/wallet/chain/c/backend.go b/wallet/chain/c/backend.go index 0a735116b646..b88c8c643bc3 100644 --- a/wallet/chain/c/backend.go +++ b/wallet/chain/c/backend.go @@ -3,153 +3,153 @@ package c -import ( - "errors" - "fmt" - "math/big" - "sync" - - stdcontext "context" - - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/utils/math" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var ( - _ Backend = (*backend)(nil) - - errUnknownTxType = errors.New("unknown tx type") -) - -// Backend defines the full interface required to support a C-chain wallet. -type Backend interface { - common.ChainUTXOs - BuilderBackend - SignerBackend - - AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error -} - -type backend struct { - Context - common.ChainUTXOs - - accountsLock sync.RWMutex - accounts map[ethcommon.Address]*Account -} - -type Account struct { - Balance *big.Int - Nonce uint64 -} - -func NewBackend( - ctx Context, - utxos common.ChainUTXOs, - accounts map[ethcommon.Address]*Account, -) Backend { - return &backend{ - Context: ctx, - ChainUTXOs: utxos, - accounts: accounts, - } -} - -func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { - switch tx := tx.UnsignedAtomicTx.(type) { - case *evm.UnsignedImportTx: - for _, input := range tx.ImportedInputs { - utxoID := input.InputID() - if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { - return err - } - } - - b.accountsLock.Lock() - defer b.accountsLock.Unlock() - - for _, output := range tx.Outs { - account, ok := b.accounts[output.Address] - if !ok { - continue - } - - balance := new(big.Int).SetUint64(output.Amount) - balance.Mul(balance, avaxConversionRate) - account.Balance.Add(account.Balance, balance) - } - case *evm.UnsignedExportTx: - txID := tx.ID() - for i, out := range tx.ExportedOutputs { - err := b.AddUTXO( - ctx, - tx.DestinationChain, - &avax.UTXO{ - UTXOID: avax.UTXOID{ - TxID: txID, - OutputIndex: uint32(i), - }, - Asset: avax.Asset{ID: out.AssetID()}, - Out: out.Out, - }, - ) - if err != nil { - return err - } - } - - b.accountsLock.Lock() - defer b.accountsLock.Unlock() - - for _, input := range tx.Ins { - account, ok := b.accounts[input.Address] - if !ok { - continue - } - - balance := new(big.Int).SetUint64(input.Amount) - balance.Mul(balance, avaxConversionRate) - if account.Balance.Cmp(balance) == -1 { - return errInsufficientFunds - } - account.Balance.Sub(account.Balance, balance) - - newNonce, err := math.Add64(input.Nonce, 1) - if err != nil { - return err - } - account.Nonce = newNonce - } - default: - return fmt.Errorf("%w: %T", errUnknownTxType, tx) - } - return nil -} - -func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { - b.accountsLock.RLock() - defer b.accountsLock.RUnlock() - - account, exists := b.accounts[addr] - if !exists { - return nil, database.ErrNotFound - } - return account.Balance, nil -} - -func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { - b.accountsLock.RLock() - defer b.accountsLock.RUnlock() - - account, exists := b.accounts[addr] - if !exists { - return 0, database.ErrNotFound - } - return account.Nonce, nil -} +// import ( +// "errors" +// "fmt" +// "math/big" +// "sync" + +// stdcontext "context" + +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/database" +// "github.com/ava-labs/avalanchego/utils/math" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var ( +// _ Backend = (*backend)(nil) + +// errUnknownTxType = errors.New("unknown tx type") +// ) + +// // Backend defines the full interface required to support a C-chain wallet. +// type Backend interface { +// common.ChainUTXOs +// BuilderBackend +// SignerBackend + +// AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error +// } + +// type backend struct { +// Context +// common.ChainUTXOs + +// accountsLock sync.RWMutex +// accounts map[ethcommon.Address]*Account +// } + +// type Account struct { +// Balance *big.Int +// Nonce uint64 +// } + +// func NewBackend( +// ctx Context, +// utxos common.ChainUTXOs, +// accounts map[ethcommon.Address]*Account, +// ) Backend { +// return &backend{ +// Context: ctx, +// ChainUTXOs: utxos, +// accounts: accounts, +// } +// } + +// func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { +// switch tx := tx.UnsignedAtomicTx.(type) { +// case *evm.UnsignedImportTx: +// for _, input := range tx.ImportedInputs { +// utxoID := input.InputID() +// if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { +// return err +// } +// } + +// b.accountsLock.Lock() +// defer b.accountsLock.Unlock() + +// for _, output := range tx.Outs { +// account, ok := b.accounts[output.Address] +// if !ok { +// continue +// } + +// balance := new(big.Int).SetUint64(output.Amount) +// balance.Mul(balance, avaxConversionRate) +// account.Balance.Add(account.Balance, balance) +// } +// case *evm.UnsignedExportTx: +// txID := tx.ID() +// for i, out := range tx.ExportedOutputs { +// err := b.AddUTXO( +// ctx, +// tx.DestinationChain, +// &avax.UTXO{ +// UTXOID: avax.UTXOID{ +// TxID: txID, +// OutputIndex: uint32(i), +// }, +// Asset: avax.Asset{ID: out.AssetID()}, +// Out: out.Out, +// }, +// ) +// if err != nil { +// return err +// } +// } + +// b.accountsLock.Lock() +// defer b.accountsLock.Unlock() + +// for _, input := range tx.Ins { +// account, ok := b.accounts[input.Address] +// if !ok { +// continue +// } + +// balance := new(big.Int).SetUint64(input.Amount) +// balance.Mul(balance, avaxConversionRate) +// if account.Balance.Cmp(balance) == -1 { +// return errInsufficientFunds +// } +// account.Balance.Sub(account.Balance, balance) + +// newNonce, err := math.Add64(input.Nonce, 1) +// if err != nil { +// return err +// } +// account.Nonce = newNonce +// } +// default: +// return fmt.Errorf("%w: %T", errUnknownTxType, tx) +// } +// return nil +// } + +// func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { +// b.accountsLock.RLock() +// defer b.accountsLock.RUnlock() + +// account, exists := b.accounts[addr] +// if !exists { +// return nil, database.ErrNotFound +// } +// return account.Balance, nil +// } + +// func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { +// b.accountsLock.RLock() +// defer b.accountsLock.RUnlock() + +// account, exists := b.accounts[addr] +// if !exists { +// return 0, database.ErrNotFound +// } +// return account.Nonce, nil +// } diff --git a/wallet/chain/c/builder.go b/wallet/chain/c/builder.go index d2d088e88a53..c51d2647777e 100644 --- a/wallet/chain/c/builder.go +++ b/wallet/chain/c/builder.go @@ -3,399 +3,399 @@ package c -import ( - "errors" - "math/big" - - stdcontext "context" - - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils" - "github.com/ava-labs/avalanchego/utils/math" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -const avaxConversionRateInt = 1_000_000_000 - -var ( - _ Builder = (*builder)(nil) - - errInsufficientFunds = errors.New("insufficient funds") - - // avaxConversionRate is the conversion rate between the smallest - // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest - // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. - // - // This is only required for AVAX because the denomination of 1 AVAX is 9 - // decimal places on the X and P chains, but is 18 decimal places within the - // EVM. - avaxConversionRate = big.NewInt(avaxConversionRateInt) -) - -// Builder provides a convenient interface for building unsigned C-chain -// transactions. -type Builder interface { - // GetBalance calculates the amount of AVAX that this builder has control - // over. - GetBalance( - options ...common.Option, - ) (*big.Int, error) - - // GetImportableBalance calculates the amount of AVAX that this builder - // could import from the provided chain. - // - // - [chainID] specifies the chain the funds are from. - GetImportableBalance( - chainID ids.ID, - options ...common.Option, - ) (uint64, error) - - // NewImportTx creates an import transaction that attempts to consume all - // the available UTXOs and import the funds to [to]. - // - // - [chainID] specifies the chain to be importing funds from. - // - [to] specifies where to send the imported funds to. - // - [baseFee] specifies the fee price willing to be paid by this tx. - NewImportTx( - chainID ids.ID, - to ethcommon.Address, - baseFee *big.Int, - options ...common.Option, - ) (*evm.UnsignedImportTx, error) - - // NewExportTx creates an export transaction that attempts to send all the - // provided [outputs] to the requested [chainID]. - // - // - [chainID] specifies the chain to be exporting the funds to. - // - [outputs] specifies the outputs to send to the [chainID]. - // - [baseFee] specifies the fee price willing to be paid by this tx. - NewExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - baseFee *big.Int, - options ...common.Option, - ) (*evm.UnsignedExportTx, error) -} - -// BuilderBackend specifies the required information needed to build unsigned -// C-chain transactions. -type BuilderBackend interface { - Context - - UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) - Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) - Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) -} - -type builder struct { - avaxAddrs set.Set[ids.ShortID] - ethAddrs set.Set[ethcommon.Address] - backend BuilderBackend -} - -// NewBuilder returns a new transaction builder. -// -// - [avaxAddrs] is the set of addresses in the AVAX format that the builder -// assumes can be used when signing the transactions in the future. -// - [ethAddrs] is the set of addresses in the Eth format that the builder -// assumes can be used when signing the transactions in the future. -// - [backend] provides the required access to the chain's context and state -// to build out the transactions. -func NewBuilder( - avaxAddrs set.Set[ids.ShortID], - ethAddrs set.Set[ethcommon.Address], - backend BuilderBackend, -) Builder { - return &builder{ - avaxAddrs: avaxAddrs, - ethAddrs: ethAddrs, - backend: backend, - } -} - -func (b *builder) GetBalance( - options ...common.Option, -) (*big.Int, error) { - var ( - ops = common.NewOptions(options) - ctx = ops.Context() - addrs = ops.EthAddresses(b.ethAddrs) - totalBalance = new(big.Int) - ) - for addr := range addrs { - balance, err := b.backend.Balance(ctx, addr) - if err != nil { - return nil, err - } - totalBalance.Add(totalBalance, balance) - } - - return totalBalance, nil -} - -func (b *builder) GetImportableBalance( - chainID ids.ID, - options ...common.Option, -) (uint64, error) { - ops := common.NewOptions(options) - utxos, err := b.backend.UTXOs(ops.Context(), chainID) - if err != nil { - return 0, err - } - - var ( - addrs = ops.Addresses(b.avaxAddrs) - minIssuanceTime = ops.MinIssuanceTime() - avaxAssetID = b.backend.AVAXAssetID() - balance uint64 - ) - for _, utxo := range utxos { - amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) - if !ok { - continue - } - - newBalance, err := math.Add64(balance, amount) - if err != nil { - return 0, err - } - balance = newBalance - } - - return balance, nil -} - -func (b *builder) NewImportTx( - chainID ids.ID, - to ethcommon.Address, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedImportTx, error) { - ops := common.NewOptions(options) - utxos, err := b.backend.UTXOs(ops.Context(), chainID) - if err != nil { - return nil, err - } - - var ( - addrs = ops.Addresses(b.avaxAddrs) - minIssuanceTime = ops.MinIssuanceTime() - avaxAssetID = b.backend.AVAXAssetID() - - importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) - importedAmount uint64 - ) - for _, utxo := range utxos { - amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) - if !ok { - continue - } - - importedInputs = append(importedInputs, &avax.TransferableInput{ - UTXOID: utxo.UTXOID, - Asset: utxo.Asset, - In: &secp256k1fx.TransferInput{ - Amt: amount, - Input: secp256k1fx.Input{ - SigIndices: inputSigIndices, - }, - }, - }) - - newImportedAmount, err := math.Add64(importedAmount, amount) - if err != nil { - return nil, err - } - importedAmount = newImportedAmount - } - - utils.Sort(importedInputs) - tx := &evm.UnsignedImportTx{ - NetworkID: b.backend.NetworkID(), - BlockchainID: b.backend.BlockchainID(), - SourceChain: chainID, - ImportedInputs: importedInputs, - } - - // We must initialize the bytes of the tx to calculate the initial cost - wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} - if err := wrappedTx.Sign(evm.Codec, nil); err != nil { - return nil, err - } - - gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) - if err != nil { - return nil, err - } - gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas - - txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) - if err != nil { - return nil, err - } - - if importedAmount <= txFee { - return nil, errInsufficientFunds - } - - tx.Outs = []evm.EVMOutput{{ - Address: to, - Amount: importedAmount - txFee, - AssetID: avaxAssetID, - }} - return tx, nil -} - -func (b *builder) NewExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedExportTx, error) { - var ( - avaxAssetID = b.backend.AVAXAssetID() - exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) - exportedAmount uint64 - ) - for i, output := range outputs { - exportedOutputs[i] = &avax.TransferableOutput{ - Asset: avax.Asset{ID: avaxAssetID}, - Out: output, - } - - newExportedAmount, err := math.Add64(exportedAmount, output.Amt) - if err != nil { - return nil, err - } - exportedAmount = newExportedAmount - } - - avax.SortTransferableOutputs(exportedOutputs, evm.Codec) - tx := &evm.UnsignedExportTx{ - NetworkID: b.backend.NetworkID(), - BlockchainID: b.backend.BlockchainID(), - DestinationChain: chainID, - ExportedOutputs: exportedOutputs, - } - - // We must initialize the bytes of the tx to calculate the initial cost - wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} - if err := wrappedTx.Sign(evm.Codec, nil); err != nil { - return nil, err - } - - cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) - if err != nil { - return nil, err - } - - initialFee, err := evm.CalculateDynamicFee(cost, baseFee) - if err != nil { - return nil, err - } - - amountToConsume, err := math.Add64(exportedAmount, initialFee) - if err != nil { - return nil, err - } - - var ( - ops = common.NewOptions(options) - ctx = ops.Context() - addrs = ops.EthAddresses(b.ethAddrs) - inputs = make([]evm.EVMInput, 0, addrs.Len()) - ) - for addr := range addrs { - if amountToConsume == 0 { - break - } - - prevFee, err := evm.CalculateDynamicFee(cost, baseFee) - if err != nil { - return nil, err - } - - newCost := cost + evm.EVMInputGas - newFee, err := evm.CalculateDynamicFee(newCost, baseFee) - if err != nil { - return nil, err - } - - additionalFee := newFee - prevFee - - balance, err := b.backend.Balance(ctx, addr) - if err != nil { - return nil, err - } - - // Since the asset is AVAX, we divide by the avaxConversionRate to - // convert back to the correct denomination of AVAX that can be - // exported. - avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() - - // If the balance for [addr] is insufficient to cover the additional - // cost of adding an input to the transaction, skip adding the input - // altogether. - if avaxBalance <= additionalFee { - continue - } - - // Update the cost for the next iteration - cost = newCost - - amountToConsume, err = math.Add64(amountToConsume, additionalFee) - if err != nil { - return nil, err - } - - nonce, err := b.backend.Nonce(ctx, addr) - if err != nil { - return nil, err - } - - inputAmount := math.Min(amountToConsume, avaxBalance) - inputs = append(inputs, evm.EVMInput{ - Address: addr, - Amount: inputAmount, - AssetID: avaxAssetID, - Nonce: nonce, - }) - amountToConsume -= inputAmount - } - - if amountToConsume > 0 { - return nil, errInsufficientFunds - } - - utils.Sort(inputs) - tx.Ins = inputs - return tx, nil -} - -func getSpendableAmount( - utxo *avax.UTXO, - addrs set.Set[ids.ShortID], - minIssuanceTime uint64, - avaxAssetID ids.ID, -) (uint64, []uint32, bool) { - if utxo.Asset.ID != avaxAssetID { - // Only AVAX can be imported - return 0, nil, false - } - - out, ok := utxo.Out.(*secp256k1fx.TransferOutput) - if !ok { - // Can't import an unknown transfer output type - return 0, nil, false - } - - inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) - return out.Amt, inputSigIndices, ok -} +// import ( +// "errors" +// "math/big" + +// stdcontext "context" + +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils" +// "github.com/ava-labs/avalanchego/utils/math" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// const avaxConversionRateInt = 1_000_000_000 + +// var ( +// _ Builder = (*builder)(nil) + +// errInsufficientFunds = errors.New("insufficient funds") + +// // avaxConversionRate is the conversion rate between the smallest +// // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest +// // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. +// // +// // This is only required for AVAX because the denomination of 1 AVAX is 9 +// // decimal places on the X and P chains, but is 18 decimal places within the +// // EVM. +// avaxConversionRate = big.NewInt(avaxConversionRateInt) +// ) + +// // Builder provides a convenient interface for building unsigned C-chain +// // transactions. +// type Builder interface { +// // GetBalance calculates the amount of AVAX that this builder has control +// // over. +// GetBalance( +// options ...common.Option, +// ) (*big.Int, error) + +// // GetImportableBalance calculates the amount of AVAX that this builder +// // could import from the provided chain. +// // +// // - [chainID] specifies the chain the funds are from. +// GetImportableBalance( +// chainID ids.ID, +// options ...common.Option, +// ) (uint64, error) + +// // NewImportTx creates an import transaction that attempts to consume all +// // the available UTXOs and import the funds to [to]. +// // +// // - [chainID] specifies the chain to be importing funds from. +// // - [to] specifies where to send the imported funds to. +// // - [baseFee] specifies the fee price willing to be paid by this tx. +// NewImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedImportTx, error) + +// // NewExportTx creates an export transaction that attempts to send all the +// // provided [outputs] to the requested [chainID]. +// // +// // - [chainID] specifies the chain to be exporting the funds to. +// // - [outputs] specifies the outputs to send to the [chainID]. +// // - [baseFee] specifies the fee price willing to be paid by this tx. +// NewExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedExportTx, error) +// } + +// // BuilderBackend specifies the required information needed to build unsigned +// // C-chain transactions. +// type BuilderBackend interface { +// Context + +// UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) +// Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) +// Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) +// } + +// type builder struct { +// avaxAddrs set.Set[ids.ShortID] +// ethAddrs set.Set[ethcommon.Address] +// backend BuilderBackend +// } + +// // NewBuilder returns a new transaction builder. +// // +// // - [avaxAddrs] is the set of addresses in the AVAX format that the builder +// // assumes can be used when signing the transactions in the future. +// // - [ethAddrs] is the set of addresses in the Eth format that the builder +// // assumes can be used when signing the transactions in the future. +// // - [backend] provides the required access to the chain's context and state +// // to build out the transactions. +// func NewBuilder( +// avaxAddrs set.Set[ids.ShortID], +// ethAddrs set.Set[ethcommon.Address], +// backend BuilderBackend, +// ) Builder { +// return &builder{ +// avaxAddrs: avaxAddrs, +// ethAddrs: ethAddrs, +// backend: backend, +// } +// } + +// func (b *builder) GetBalance( +// options ...common.Option, +// ) (*big.Int, error) { +// var ( +// ops = common.NewOptions(options) +// ctx = ops.Context() +// addrs = ops.EthAddresses(b.ethAddrs) +// totalBalance = new(big.Int) +// ) +// for addr := range addrs { +// balance, err := b.backend.Balance(ctx, addr) +// if err != nil { +// return nil, err +// } +// totalBalance.Add(totalBalance, balance) +// } + +// return totalBalance, nil +// } + +// func (b *builder) GetImportableBalance( +// chainID ids.ID, +// options ...common.Option, +// ) (uint64, error) { +// ops := common.NewOptions(options) +// utxos, err := b.backend.UTXOs(ops.Context(), chainID) +// if err != nil { +// return 0, err +// } + +// var ( +// addrs = ops.Addresses(b.avaxAddrs) +// minIssuanceTime = ops.MinIssuanceTime() +// avaxAssetID = b.backend.AVAXAssetID() +// balance uint64 +// ) +// for _, utxo := range utxos { +// amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) +// if !ok { +// continue +// } + +// newBalance, err := math.Add64(balance, amount) +// if err != nil { +// return 0, err +// } +// balance = newBalance +// } + +// return balance, nil +// } + +// func (b *builder) NewImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedImportTx, error) { +// ops := common.NewOptions(options) +// utxos, err := b.backend.UTXOs(ops.Context(), chainID) +// if err != nil { +// return nil, err +// } + +// var ( +// addrs = ops.Addresses(b.avaxAddrs) +// minIssuanceTime = ops.MinIssuanceTime() +// avaxAssetID = b.backend.AVAXAssetID() + +// importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) +// importedAmount uint64 +// ) +// for _, utxo := range utxos { +// amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) +// if !ok { +// continue +// } + +// importedInputs = append(importedInputs, &avax.TransferableInput{ +// UTXOID: utxo.UTXOID, +// Asset: utxo.Asset, +// In: &secp256k1fx.TransferInput{ +// Amt: amount, +// Input: secp256k1fx.Input{ +// SigIndices: inputSigIndices, +// }, +// }, +// }) + +// newImportedAmount, err := math.Add64(importedAmount, amount) +// if err != nil { +// return nil, err +// } +// importedAmount = newImportedAmount +// } + +// utils.Sort(importedInputs) +// tx := &evm.UnsignedImportTx{ +// NetworkID: b.backend.NetworkID(), +// BlockchainID: b.backend.BlockchainID(), +// SourceChain: chainID, +// ImportedInputs: importedInputs, +// } + +// // We must initialize the bytes of the tx to calculate the initial cost +// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} +// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { +// return nil, err +// } + +// gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) +// if err != nil { +// return nil, err +// } +// gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas + +// txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) +// if err != nil { +// return nil, err +// } + +// if importedAmount <= txFee { +// return nil, errInsufficientFunds +// } + +// tx.Outs = []evm.EVMOutput{{ +// Address: to, +// Amount: importedAmount - txFee, +// AssetID: avaxAssetID, +// }} +// return tx, nil +// } + +// func (b *builder) NewExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedExportTx, error) { +// var ( +// avaxAssetID = b.backend.AVAXAssetID() +// exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) +// exportedAmount uint64 +// ) +// for i, output := range outputs { +// exportedOutputs[i] = &avax.TransferableOutput{ +// Asset: avax.Asset{ID: avaxAssetID}, +// Out: output, +// } + +// newExportedAmount, err := math.Add64(exportedAmount, output.Amt) +// if err != nil { +// return nil, err +// } +// exportedAmount = newExportedAmount +// } + +// avax.SortTransferableOutputs(exportedOutputs, evm.Codec) +// tx := &evm.UnsignedExportTx{ +// NetworkID: b.backend.NetworkID(), +// BlockchainID: b.backend.BlockchainID(), +// DestinationChain: chainID, +// ExportedOutputs: exportedOutputs, +// } + +// // We must initialize the bytes of the tx to calculate the initial cost +// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} +// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { +// return nil, err +// } + +// cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) +// if err != nil { +// return nil, err +// } + +// initialFee, err := evm.CalculateDynamicFee(cost, baseFee) +// if err != nil { +// return nil, err +// } + +// amountToConsume, err := math.Add64(exportedAmount, initialFee) +// if err != nil { +// return nil, err +// } + +// var ( +// ops = common.NewOptions(options) +// ctx = ops.Context() +// addrs = ops.EthAddresses(b.ethAddrs) +// inputs = make([]evm.EVMInput, 0, addrs.Len()) +// ) +// for addr := range addrs { +// if amountToConsume == 0 { +// break +// } + +// prevFee, err := evm.CalculateDynamicFee(cost, baseFee) +// if err != nil { +// return nil, err +// } + +// newCost := cost + evm.EVMInputGas +// newFee, err := evm.CalculateDynamicFee(newCost, baseFee) +// if err != nil { +// return nil, err +// } + +// additionalFee := newFee - prevFee + +// balance, err := b.backend.Balance(ctx, addr) +// if err != nil { +// return nil, err +// } + +// // Since the asset is AVAX, we divide by the avaxConversionRate to +// // convert back to the correct denomination of AVAX that can be +// // exported. +// avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() + +// // If the balance for [addr] is insufficient to cover the additional +// // cost of adding an input to the transaction, skip adding the input +// // altogether. +// if avaxBalance <= additionalFee { +// continue +// } + +// // Update the cost for the next iteration +// cost = newCost + +// amountToConsume, err = math.Add64(amountToConsume, additionalFee) +// if err != nil { +// return nil, err +// } + +// nonce, err := b.backend.Nonce(ctx, addr) +// if err != nil { +// return nil, err +// } + +// inputAmount := math.Min(amountToConsume, avaxBalance) +// inputs = append(inputs, evm.EVMInput{ +// Address: addr, +// Amount: inputAmount, +// AssetID: avaxAssetID, +// Nonce: nonce, +// }) +// amountToConsume -= inputAmount +// } + +// if amountToConsume > 0 { +// return nil, errInsufficientFunds +// } + +// utils.Sort(inputs) +// tx.Ins = inputs +// return tx, nil +// } + +// func getSpendableAmount( +// utxo *avax.UTXO, +// addrs set.Set[ids.ShortID], +// minIssuanceTime uint64, +// avaxAssetID ids.ID, +// ) (uint64, []uint32, bool) { +// if utxo.Asset.ID != avaxAssetID { +// // Only AVAX can be imported +// return 0, nil, false +// } + +// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) +// if !ok { +// // Can't import an unknown transfer output type +// return 0, nil, false +// } + +// inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) +// return out.Amt, inputSigIndices, ok +// } diff --git a/wallet/chain/c/builder_with_options.go b/wallet/chain/c/builder_with_options.go index 8416dddf9928..9b7ab8399484 100644 --- a/wallet/chain/c/builder_with_options.go +++ b/wallet/chain/c/builder_with_options.go @@ -3,81 +3,81 @@ package c -import ( - "math/big" +// import ( +// "math/big" - "github.com/ava-labs/coreth/plugin/evm" +// "github.com/ava-labs/coreth/plugin/evm" - ethcommon "github.com/ethereum/go-ethereum/common" +// ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) -var _ Builder = (*builderWithOptions)(nil) +// var _ Builder = (*builderWithOptions)(nil) -type builderWithOptions struct { - Builder - options []common.Option -} +// type builderWithOptions struct { +// Builder +// options []common.Option +// } -// NewBuilderWithOptions returns a new transaction builder that will use the -// given options by default. -// -// - [builder] is the builder that will be called to perform the underlying -// operations. -// - [options] will be provided to the builder in addition to the options -// provided in the method calls. -func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { - return &builderWithOptions{ - Builder: builder, - options: options, - } -} +// // NewBuilderWithOptions returns a new transaction builder that will use the +// // given options by default. +// // +// // - [builder] is the builder that will be called to perform the underlying +// // operations. +// // - [options] will be provided to the builder in addition to the options +// // provided in the method calls. +// func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { +// return &builderWithOptions{ +// Builder: builder, +// options: options, +// } +// } -func (b *builderWithOptions) GetBalance( - options ...common.Option, -) (*big.Int, error) { - return b.Builder.GetBalance( - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) GetBalance( +// options ...common.Option, +// ) (*big.Int, error) { +// return b.Builder.GetBalance( +// common.UnionOptions(b.options, options)..., +// ) +// } -func (b *builderWithOptions) GetImportableBalance( - chainID ids.ID, - options ...common.Option, -) (uint64, error) { - return b.Builder.GetImportableBalance( - chainID, - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) GetImportableBalance( +// chainID ids.ID, +// options ...common.Option, +// ) (uint64, error) { +// return b.Builder.GetImportableBalance( +// chainID, +// common.UnionOptions(b.options, options)..., +// ) +// } -func (b *builderWithOptions) NewImportTx( - chainID ids.ID, - to ethcommon.Address, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedImportTx, error) { - return b.Builder.NewImportTx( - chainID, - to, - baseFee, - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) NewImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedImportTx, error) { +// return b.Builder.NewImportTx( +// chainID, +// to, +// baseFee, +// common.UnionOptions(b.options, options)..., +// ) +// } -func (b *builderWithOptions) NewExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedExportTx, error) { - return b.Builder.NewExportTx( - chainID, - outputs, - baseFee, - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) NewExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedExportTx, error) { +// return b.Builder.NewExportTx( +// chainID, +// outputs, +// baseFee, +// common.UnionOptions(b.options, options)..., +// ) +// } diff --git a/wallet/chain/c/context.go b/wallet/chain/c/context.go index d506b42f81fa..1c01d8fb55c8 100644 --- a/wallet/chain/c/context.go +++ b/wallet/chain/c/context.go @@ -3,81 +3,81 @@ package c -import ( - stdcontext "context" +// import ( +// stdcontext "context" - "github.com/ava-labs/avalanchego/api/info" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/avm" -) +// "github.com/ava-labs/avalanchego/api/info" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/avm" +// ) -var _ Context = (*context)(nil) +// var _ Context = (*context)(nil) -type Context interface { - NetworkID() uint32 - BlockchainID() ids.ID - AVAXAssetID() ids.ID -} +// type Context interface { +// NetworkID() uint32 +// BlockchainID() ids.ID +// AVAXAssetID() ids.ID +// } -type context struct { - networkID uint32 - blockchainID ids.ID - avaxAssetID ids.ID -} +// type context struct { +// networkID uint32 +// blockchainID ids.ID +// avaxAssetID ids.ID +// } -func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { - infoClient := info.NewClient(uri) - xChainClient := avm.NewClient(uri, "X") - return NewContextFromClients(ctx, infoClient, xChainClient) -} +// func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { +// infoClient := info.NewClient(uri) +// xChainClient := avm.NewClient(uri, "X") +// return NewContextFromClients(ctx, infoClient, xChainClient) +// } -func NewContextFromClients( - ctx stdcontext.Context, - infoClient info.Client, - xChainClient avm.Client, -) (Context, error) { - networkID, err := infoClient.GetNetworkID(ctx) - if err != nil { - return nil, err - } +// func NewContextFromClients( +// ctx stdcontext.Context, +// infoClient info.Client, +// xChainClient avm.Client, +// ) (Context, error) { +// networkID, err := infoClient.GetNetworkID(ctx) +// if err != nil { +// return nil, err +// } - chainID, err := infoClient.GetBlockchainID(ctx, "C") - if err != nil { - return nil, err - } +// chainID, err := infoClient.GetBlockchainID(ctx, "C") +// if err != nil { +// return nil, err +// } - asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") - if err != nil { - return nil, err - } +// asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") +// if err != nil { +// return nil, err +// } - return NewContext( - networkID, - chainID, - asset.AssetID, - ), nil -} +// return NewContext( +// networkID, +// chainID, +// asset.AssetID, +// ), nil +// } -func NewContext( - networkID uint32, - blockchainID ids.ID, - avaxAssetID ids.ID, -) Context { - return &context{ - networkID: networkID, - blockchainID: blockchainID, - avaxAssetID: avaxAssetID, - } -} +// func NewContext( +// networkID uint32, +// blockchainID ids.ID, +// avaxAssetID ids.ID, +// ) Context { +// return &context{ +// networkID: networkID, +// blockchainID: blockchainID, +// avaxAssetID: avaxAssetID, +// } +// } -func (c *context) NetworkID() uint32 { - return c.networkID -} +// func (c *context) NetworkID() uint32 { +// return c.networkID +// } -func (c *context) BlockchainID() ids.ID { - return c.blockchainID -} +// func (c *context) BlockchainID() ids.ID { +// return c.blockchainID +// } -func (c *context) AVAXAssetID() ids.ID { - return c.avaxAssetID -} +// func (c *context) AVAXAssetID() ids.ID { +// return c.avaxAssetID +// } diff --git a/wallet/chain/c/signer.go b/wallet/chain/c/signer.go index 4fd85ed3b532..4bedc378234b 100644 --- a/wallet/chain/c/signer.go +++ b/wallet/chain/c/signer.go @@ -3,221 +3,221 @@ package c -import ( - "errors" - "fmt" - - stdcontext "context" - - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/crypto/keychain" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/hashing" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/components/verify" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" -) - -const version = 0 - -var ( - _ Signer = (*txSigner)(nil) - - errUnknownInputType = errors.New("unknown input type") - errUnknownCredentialType = errors.New("unknown credential type") - errUnknownOutputType = errors.New("unknown output type") - errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") - - emptySig [secp256k1.SignatureLen]byte -) - -type Signer interface { - SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) - SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error -} - -type EthKeychain interface { - // The returned Signer can provide a signature for [addr] - GetEth(addr ethcommon.Address) (keychain.Signer, bool) - // Returns the set of addresses for which the accessor keeps an associated - // signer - EthAddresses() set.Set[ethcommon.Address] -} - -type SignerBackend interface { - GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) -} - -type txSigner struct { - avaxKC keychain.Keychain - ethKC EthKeychain - backend SignerBackend -} - -func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { - return &txSigner{ - avaxKC: avaxKC, - ethKC: ethKC, - backend: backend, - } -} - -func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { - tx := &evm.Tx{UnsignedAtomicTx: utx} - return tx, s.SignAtomic(ctx, tx) -} - -func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { - switch utx := tx.UnsignedAtomicTx.(type) { - case *evm.UnsignedImportTx: - signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) - if err != nil { - return err - } - return sign(tx, true, signers) - case *evm.UnsignedExportTx: - signers := s.getExportSigners(utx.Ins) - return sign(tx, true, signers) - default: - return fmt.Errorf("%w: %T", errUnknownTxType, tx) - } -} - -func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { - txSigners := make([][]keychain.Signer, len(ins)) - for credIndex, transferInput := range ins { - input, ok := transferInput.In.(*secp256k1fx.TransferInput) - if !ok { - return nil, errUnknownInputType - } - - inputSigners := make([]keychain.Signer, len(input.SigIndices)) - txSigners[credIndex] = inputSigners - - utxoID := transferInput.InputID() - utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) - if err == database.ErrNotFound { - // If we don't have access to the UTXO, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - if err != nil { - return nil, err - } - - out, ok := utxo.Out.(*secp256k1fx.TransferOutput) - if !ok { - return nil, errUnknownOutputType - } - - for sigIndex, addrIndex := range input.SigIndices { - if addrIndex >= uint32(len(out.Addrs)) { - return nil, errInvalidUTXOSigIndex - } - - addr := out.Addrs[addrIndex] - key, ok := s.avaxKC.Get(addr) - if !ok { - // If we don't have access to the key, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - inputSigners[sigIndex] = key - } - } - return txSigners, nil -} - -func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { - txSigners := make([][]keychain.Signer, len(ins)) - for credIndex, input := range ins { - inputSigners := make([]keychain.Signer, 1) - txSigners[credIndex] = inputSigners - - key, ok := s.ethKC.GetEth(input.Address) - if !ok { - // If we don't have access to the key, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - inputSigners[0] = key - } - return txSigners -} - -// TODO: remove [signHash] after the ledger supports signing all transactions. -func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { - unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) - if err != nil { - return fmt.Errorf("couldn't marshal unsigned tx: %w", err) - } - unsignedHash := hashing.ComputeHash256(unsignedBytes) - - if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { - tx.Creds = make([]verify.Verifiable, expectedLen) - } - - sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) - for credIndex, inputSigners := range txSigners { - credIntf := tx.Creds[credIndex] - if credIntf == nil { - credIntf = &secp256k1fx.Credential{} - tx.Creds[credIndex] = credIntf - } - - cred, ok := credIntf.(*secp256k1fx.Credential) - if !ok { - return errUnknownCredentialType - } - if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { - cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) - } - - for sigIndex, signer := range inputSigners { - if signer == nil { - // If we don't have access to the key, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - addr := signer.Address() - if sig := cred.Sigs[sigIndex]; sig != emptySig { - // If this signature has already been populated, we can just - // copy the needed signature for the future. - sigCache[addr] = sig - continue - } - - if sig, exists := sigCache[addr]; exists { - // If this key has already produced a signature, we can just - // copy the previous signature. - cred.Sigs[sigIndex] = sig - continue - } - - var sig []byte - if signHash { - sig, err = signer.SignHash(unsignedHash) - } else { - sig, err = signer.Sign(unsignedBytes) - } - if err != nil { - return fmt.Errorf("problem signing tx: %w", err) - } - copy(cred.Sigs[sigIndex][:], sig) - sigCache[addr] = cred.Sigs[sigIndex] - } - } - - signedBytes, err := evm.Codec.Marshal(version, tx) - if err != nil { - return fmt.Errorf("couldn't marshal tx: %w", err) - } - tx.Initialize(unsignedBytes, signedBytes) - return nil -} +// import ( +// "errors" +// "fmt" + +// stdcontext "context" + +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/database" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils/crypto/keychain" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/hashing" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/components/verify" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// ) + +// const version = 0 + +// var ( +// _ Signer = (*txSigner)(nil) + +// errUnknownInputType = errors.New("unknown input type") +// errUnknownCredentialType = errors.New("unknown credential type") +// errUnknownOutputType = errors.New("unknown output type") +// errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") + +// emptySig [secp256k1.SignatureLen]byte +// ) + +// type Signer interface { +// SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) +// SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error +// } + +// type EthKeychain interface { +// // The returned Signer can provide a signature for [addr] +// GetEth(addr ethcommon.Address) (keychain.Signer, bool) +// // Returns the set of addresses for which the accessor keeps an associated +// // signer +// EthAddresses() set.Set[ethcommon.Address] +// } + +// type SignerBackend interface { +// GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) +// } + +// type txSigner struct { +// avaxKC keychain.Keychain +// ethKC EthKeychain +// backend SignerBackend +// } + +// func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { +// return &txSigner{ +// avaxKC: avaxKC, +// ethKC: ethKC, +// backend: backend, +// } +// } + +// func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { +// tx := &evm.Tx{UnsignedAtomicTx: utx} +// return tx, s.SignAtomic(ctx, tx) +// } + +// func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { +// switch utx := tx.UnsignedAtomicTx.(type) { +// case *evm.UnsignedImportTx: +// signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) +// if err != nil { +// return err +// } +// return sign(tx, true, signers) +// case *evm.UnsignedExportTx: +// signers := s.getExportSigners(utx.Ins) +// return sign(tx, true, signers) +// default: +// return fmt.Errorf("%w: %T", errUnknownTxType, tx) +// } +// } + +// func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { +// txSigners := make([][]keychain.Signer, len(ins)) +// for credIndex, transferInput := range ins { +// input, ok := transferInput.In.(*secp256k1fx.TransferInput) +// if !ok { +// return nil, errUnknownInputType +// } + +// inputSigners := make([]keychain.Signer, len(input.SigIndices)) +// txSigners[credIndex] = inputSigners + +// utxoID := transferInput.InputID() +// utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) +// if err == database.ErrNotFound { +// // If we don't have access to the UTXO, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// if err != nil { +// return nil, err +// } + +// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) +// if !ok { +// return nil, errUnknownOutputType +// } + +// for sigIndex, addrIndex := range input.SigIndices { +// if addrIndex >= uint32(len(out.Addrs)) { +// return nil, errInvalidUTXOSigIndex +// } + +// addr := out.Addrs[addrIndex] +// key, ok := s.avaxKC.Get(addr) +// if !ok { +// // If we don't have access to the key, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// inputSigners[sigIndex] = key +// } +// } +// return txSigners, nil +// } + +// func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { +// txSigners := make([][]keychain.Signer, len(ins)) +// for credIndex, input := range ins { +// inputSigners := make([]keychain.Signer, 1) +// txSigners[credIndex] = inputSigners + +// key, ok := s.ethKC.GetEth(input.Address) +// if !ok { +// // If we don't have access to the key, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// inputSigners[0] = key +// } +// return txSigners +// } + +// // TODO: remove [signHash] after the ledger supports signing all transactions. +// func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { +// unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) +// if err != nil { +// return fmt.Errorf("couldn't marshal unsigned tx: %w", err) +// } +// unsignedHash := hashing.ComputeHash256(unsignedBytes) + +// if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { +// tx.Creds = make([]verify.Verifiable, expectedLen) +// } + +// sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) +// for credIndex, inputSigners := range txSigners { +// credIntf := tx.Creds[credIndex] +// if credIntf == nil { +// credIntf = &secp256k1fx.Credential{} +// tx.Creds[credIndex] = credIntf +// } + +// cred, ok := credIntf.(*secp256k1fx.Credential) +// if !ok { +// return errUnknownCredentialType +// } +// if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { +// cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) +// } + +// for sigIndex, signer := range inputSigners { +// if signer == nil { +// // If we don't have access to the key, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// addr := signer.Address() +// if sig := cred.Sigs[sigIndex]; sig != emptySig { +// // If this signature has already been populated, we can just +// // copy the needed signature for the future. +// sigCache[addr] = sig +// continue +// } + +// if sig, exists := sigCache[addr]; exists { +// // If this key has already produced a signature, we can just +// // copy the previous signature. +// cred.Sigs[sigIndex] = sig +// continue +// } + +// var sig []byte +// if signHash { +// sig, err = signer.SignHash(unsignedHash) +// } else { +// sig, err = signer.Sign(unsignedBytes) +// } +// if err != nil { +// return fmt.Errorf("problem signing tx: %w", err) +// } +// copy(cred.Sigs[sigIndex][:], sig) +// sigCache[addr] = cred.Sigs[sigIndex] +// } +// } + +// signedBytes, err := evm.Codec.Marshal(version, tx) +// if err != nil { +// return fmt.Errorf("couldn't marshal tx: %w", err) +// } +// tx.Initialize(unsignedBytes, signedBytes) +// return nil +// } diff --git a/wallet/chain/c/wallet.go b/wallet/chain/c/wallet.go index fb1a83d53dad..ebee50a9a958 100644 --- a/wallet/chain/c/wallet.go +++ b/wallet/chain/c/wallet.go @@ -3,204 +3,204 @@ package c -import ( - "errors" - "math/big" - "time" - - "github.com/ava-labs/coreth/ethclient" - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var ( - _ Wallet = (*wallet)(nil) - - errNotCommitted = errors.New("not committed") -) - -type Wallet interface { - Context - - // Builder returns the builder that will be used to create the transactions. - Builder() Builder - - // Signer returns the signer that will be used to sign the transactions. - Signer() Signer - - // IssueImportTx creates, signs, and issues an import transaction that - // attempts to consume all the available UTXOs and import the funds to [to]. - // - // - [chainID] specifies the chain to be importing funds from. - // - [to] specifies where to send the imported funds to. - IssueImportTx( - chainID ids.ID, - to ethcommon.Address, - options ...common.Option, - ) (*evm.Tx, error) - - // IssueExportTx creates, signs, and issues an export transaction that - // attempts to send all the provided [outputs] to the requested [chainID]. - // - // - [chainID] specifies the chain to be exporting the funds to. - // - [outputs] specifies the outputs to send to the [chainID]. - IssueExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - options ...common.Option, - ) (*evm.Tx, error) - - // IssueUnsignedTx signs and issues the unsigned tx. - IssueUnsignedAtomicTx( - utx evm.UnsignedAtomicTx, - options ...common.Option, - ) (*evm.Tx, error) - - // IssueAtomicTx issues the signed tx. - IssueAtomicTx( - tx *evm.Tx, - options ...common.Option, - ) error -} - -func NewWallet( - builder Builder, - signer Signer, - avaxClient evm.Client, - ethClient ethclient.Client, - backend Backend, -) Wallet { - return &wallet{ - Backend: backend, - builder: builder, - signer: signer, - avaxClient: avaxClient, - ethClient: ethClient, - } -} - -type wallet struct { - Backend - builder Builder - signer Signer - avaxClient evm.Client - ethClient ethclient.Client -} - -func (w *wallet) Builder() Builder { - return w.builder -} - -func (w *wallet) Signer() Signer { - return w.signer -} - -func (w *wallet) IssueImportTx( - chainID ids.ID, - to ethcommon.Address, - options ...common.Option, -) (*evm.Tx, error) { - baseFee, err := w.baseFee(options) - if err != nil { - return nil, err - } - - utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) - if err != nil { - return nil, err - } - return w.IssueUnsignedAtomicTx(utx, options...) -} - -func (w *wallet) IssueExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - options ...common.Option, -) (*evm.Tx, error) { - baseFee, err := w.baseFee(options) - if err != nil { - return nil, err - } - - utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) - if err != nil { - return nil, err - } - return w.IssueUnsignedAtomicTx(utx, options...) -} - -func (w *wallet) IssueUnsignedAtomicTx( - utx evm.UnsignedAtomicTx, - options ...common.Option, -) (*evm.Tx, error) { - ops := common.NewOptions(options) - ctx := ops.Context() - tx, err := w.signer.SignUnsignedAtomic(ctx, utx) - if err != nil { - return nil, err - } - - return tx, w.IssueAtomicTx(tx, options...) -} - -func (w *wallet) IssueAtomicTx( - tx *evm.Tx, - options ...common.Option, -) error { - ops := common.NewOptions(options) - ctx := ops.Context() - txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) - if err != nil { - return err - } - - if f := ops.PostIssuanceFunc(); f != nil { - f(txID) - } - - if ops.AssumeDecided() { - return w.Backend.AcceptAtomicTx(ctx, tx) - } - - pollFrequency := ops.PollFrequency() - ticker := time.NewTicker(pollFrequency) - defer ticker.Stop() - - for { - status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) - if err != nil { - return err - } - - switch status { - case evm.Accepted: - return w.Backend.AcceptAtomicTx(ctx, tx) - case evm.Dropped, evm.Unknown: - return errNotCommitted - } - - // The tx is Processing. - - select { - case <-ticker.C: - case <-ctx.Done(): - return ctx.Err() - } - } -} - -func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { - ops := common.NewOptions(options) - baseFee := ops.BaseFee(nil) - if baseFee != nil { - return baseFee, nil - } - - ctx := ops.Context() - return w.ethClient.EstimateBaseFee(ctx) -} +// import ( +// "errors" +// "math/big" +// "time" + +// "github.com/ava-labs/coreth/ethclient" +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var ( +// _ Wallet = (*wallet)(nil) + +// errNotCommitted = errors.New("not committed") +// ) + +// type Wallet interface { +// Context + +// // Builder returns the builder that will be used to create the transactions. +// Builder() Builder + +// // Signer returns the signer that will be used to sign the transactions. +// Signer() Signer + +// // IssueImportTx creates, signs, and issues an import transaction that +// // attempts to consume all the available UTXOs and import the funds to [to]. +// // +// // - [chainID] specifies the chain to be importing funds from. +// // - [to] specifies where to send the imported funds to. +// IssueImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// options ...common.Option, +// ) (*evm.Tx, error) + +// // IssueExportTx creates, signs, and issues an export transaction that +// // attempts to send all the provided [outputs] to the requested [chainID]. +// // +// // - [chainID] specifies the chain to be exporting the funds to. +// // - [outputs] specifies the outputs to send to the [chainID]. +// IssueExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// options ...common.Option, +// ) (*evm.Tx, error) + +// // IssueUnsignedTx signs and issues the unsigned tx. +// IssueUnsignedAtomicTx( +// utx evm.UnsignedAtomicTx, +// options ...common.Option, +// ) (*evm.Tx, error) + +// // IssueAtomicTx issues the signed tx. +// IssueAtomicTx( +// tx *evm.Tx, +// options ...common.Option, +// ) error +// } + +// func NewWallet( +// builder Builder, +// signer Signer, +// avaxClient evm.Client, +// ethClient ethclient.Client, +// backend Backend, +// ) Wallet { +// return &wallet{ +// Backend: backend, +// builder: builder, +// signer: signer, +// avaxClient: avaxClient, +// ethClient: ethClient, +// } +// } + +// type wallet struct { +// Backend +// builder Builder +// signer Signer +// avaxClient evm.Client +// ethClient ethclient.Client +// } + +// func (w *wallet) Builder() Builder { +// return w.builder +// } + +// func (w *wallet) Signer() Signer { +// return w.signer +// } + +// func (w *wallet) IssueImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// options ...common.Option, +// ) (*evm.Tx, error) { +// baseFee, err := w.baseFee(options) +// if err != nil { +// return nil, err +// } + +// utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) +// if err != nil { +// return nil, err +// } +// return w.IssueUnsignedAtomicTx(utx, options...) +// } + +// func (w *wallet) IssueExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// options ...common.Option, +// ) (*evm.Tx, error) { +// baseFee, err := w.baseFee(options) +// if err != nil { +// return nil, err +// } + +// utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) +// if err != nil { +// return nil, err +// } +// return w.IssueUnsignedAtomicTx(utx, options...) +// } + +// func (w *wallet) IssueUnsignedAtomicTx( +// utx evm.UnsignedAtomicTx, +// options ...common.Option, +// ) (*evm.Tx, error) { +// ops := common.NewOptions(options) +// ctx := ops.Context() +// tx, err := w.signer.SignUnsignedAtomic(ctx, utx) +// if err != nil { +// return nil, err +// } + +// return tx, w.IssueAtomicTx(tx, options...) +// } + +// func (w *wallet) IssueAtomicTx( +// tx *evm.Tx, +// options ...common.Option, +// ) error { +// ops := common.NewOptions(options) +// ctx := ops.Context() +// txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) +// if err != nil { +// return err +// } + +// if f := ops.PostIssuanceFunc(); f != nil { +// f(txID) +// } + +// if ops.AssumeDecided() { +// return w.Backend.AcceptAtomicTx(ctx, tx) +// } + +// pollFrequency := ops.PollFrequency() +// ticker := time.NewTicker(pollFrequency) +// defer ticker.Stop() + +// for { +// status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) +// if err != nil { +// return err +// } + +// switch status { +// case evm.Accepted: +// return w.Backend.AcceptAtomicTx(ctx, tx) +// case evm.Dropped, evm.Unknown: +// return errNotCommitted +// } + +// // The tx is Processing. + +// select { +// case <-ticker.C: +// case <-ctx.Done(): +// return ctx.Err() +// } +// } +// } + +// func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { +// ops := common.NewOptions(options) +// baseFee := ops.BaseFee(nil) +// if baseFee != nil { +// return baseFee, nil +// } + +// ctx := ops.Context() +// return w.ethClient.EstimateBaseFee(ctx) +// } diff --git a/wallet/chain/c/wallet_with_options.go b/wallet/chain/c/wallet_with_options.go index 7d6193683d49..fd69a6d4fd02 100644 --- a/wallet/chain/c/wallet_with_options.go +++ b/wallet/chain/c/wallet_with_options.go @@ -3,80 +3,80 @@ package c -import ( - "github.com/ava-labs/coreth/plugin/evm" +// import ( +// "github.com/ava-labs/coreth/plugin/evm" - ethcommon "github.com/ethereum/go-ethereum/common" +// ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) -var _ Wallet = (*walletWithOptions)(nil) +// var _ Wallet = (*walletWithOptions)(nil) -func NewWalletWithOptions( - wallet Wallet, - options ...common.Option, -) Wallet { - return &walletWithOptions{ - Wallet: wallet, - options: options, - } -} +// func NewWalletWithOptions( +// wallet Wallet, +// options ...common.Option, +// ) Wallet { +// return &walletWithOptions{ +// Wallet: wallet, +// options: options, +// } +// } -type walletWithOptions struct { - Wallet - options []common.Option -} +// type walletWithOptions struct { +// Wallet +// options []common.Option +// } -func (w *walletWithOptions) Builder() Builder { - return NewBuilderWithOptions( - w.Wallet.Builder(), - w.options..., - ) -} +// func (w *walletWithOptions) Builder() Builder { +// return NewBuilderWithOptions( +// w.Wallet.Builder(), +// w.options..., +// ) +// } -func (w *walletWithOptions) IssueImportTx( - chainID ids.ID, - to ethcommon.Address, - options ...common.Option, -) (*evm.Tx, error) { - return w.Wallet.IssueImportTx( - chainID, - to, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// options ...common.Option, +// ) (*evm.Tx, error) { +// return w.Wallet.IssueImportTx( +// chainID, +// to, +// common.UnionOptions(w.options, options)..., +// ) +// } -func (w *walletWithOptions) IssueExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - options ...common.Option, -) (*evm.Tx, error) { - return w.Wallet.IssueExportTx( - chainID, - outputs, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// options ...common.Option, +// ) (*evm.Tx, error) { +// return w.Wallet.IssueExportTx( +// chainID, +// outputs, +// common.UnionOptions(w.options, options)..., +// ) +// } -func (w *walletWithOptions) IssueUnsignedAtomicTx( - utx evm.UnsignedAtomicTx, - options ...common.Option, -) (*evm.Tx, error) { - return w.Wallet.IssueUnsignedAtomicTx( - utx, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueUnsignedAtomicTx( +// utx evm.UnsignedAtomicTx, +// options ...common.Option, +// ) (*evm.Tx, error) { +// return w.Wallet.IssueUnsignedAtomicTx( +// utx, +// common.UnionOptions(w.options, options)..., +// ) +// } -func (w *walletWithOptions) IssueAtomicTx( - tx *evm.Tx, - options ...common.Option, -) error { - return w.Wallet.IssueAtomicTx( - tx, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueAtomicTx( +// tx *evm.Tx, +// options ...common.Option, +// ) error { +// return w.Wallet.IssueAtomicTx( +// tx, +// common.UnionOptions(w.options, options)..., +// ) +// } diff --git a/wallet/subnet/primary/api.go b/wallet/subnet/primary/api.go index 3ac72c217884..3260c05a0a1b 100644 --- a/wallet/subnet/primary/api.go +++ b/wallet/subnet/primary/api.go @@ -5,12 +5,6 @@ package primary import ( "context" - "fmt" - - "github.com/ava-labs/coreth/ethclient" - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ethereum/go-ethereum/common" "github.com/ava-labs/avalanchego/api/info" "github.com/ava-labs/avalanchego/codec" @@ -22,7 +16,6 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm" "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" ) @@ -59,9 +52,9 @@ type AVAXState struct { PCTX p.Context XClient avm.Client XCTX x.Context - CClient evm.Client - CCTX c.Context - UTXOs UTXOs + // CClient evm.Client + // CCTX c.Context + UTXOs UTXOs } func FetchState( @@ -75,7 +68,7 @@ func FetchState( infoClient := info.NewClient(uri) pClient := platformvm.NewClient(uri) xClient := avm.NewClient(uri, "X") - cClient := evm.NewCChainClient(uri) + // cClient := evm.NewCChainClient(uri) pCTX, err := p.NewContextFromClients(ctx, infoClient, xClient) if err != nil { @@ -87,10 +80,10 @@ func FetchState( return nil, err } - cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) - if err != nil { - return nil, err - } + // cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) + // if err != nil { + // return nil, err + // } utxos := NewUTXOs() addrList := addrs.List() @@ -109,11 +102,11 @@ func FetchState( client: xClient, codec: x.Parser.Codec(), }, - { - id: cCTX.BlockchainID(), - client: cClient, - codec: evm.Codec, - }, + // { + // id: cCTX.BlockchainID(), + // client: cClient, + // codec: evm.Codec, + // }, } for _, destinationChain := range chains { for _, sourceChain := range chains { @@ -136,52 +129,52 @@ func FetchState( PCTX: pCTX, XClient: xClient, XCTX: xCTX, - CClient: cClient, - CCTX: cCTX, - UTXOs: utxos, + // CClient: cClient, + // CCTX: cCTX, + UTXOs: utxos, }, nil } -type EthState struct { - Client ethclient.Client - Accounts map[common.Address]*c.Account -} - -func FetchEthState( - ctx context.Context, - uri string, - addrs set.Set[common.Address], -) (*EthState, error) { - path := fmt.Sprintf( - "%s/ext/%s/C/rpc", - uri, - constants.ChainAliasPrefix, - ) - client, err := ethclient.Dial(path) - if err != nil { - return nil, err - } - - accounts := make(map[common.Address]*c.Account, addrs.Len()) - for addr := range addrs { - balance, err := client.BalanceAt(ctx, addr, nil) - if err != nil { - return nil, err - } - nonce, err := client.NonceAt(ctx, addr, nil) - if err != nil { - return nil, err - } - accounts[addr] = &c.Account{ - Balance: balance, - Nonce: nonce, - } - } - return &EthState{ - Client: client, - Accounts: accounts, - }, nil -} +// type EthState struct { +// Client ethclient.Client +// Accounts map[common.Address]*c.Account +// } + +// func FetchEthState( +// ctx context.Context, +// uri string, +// addrs set.Set[common.Address], +// ) (*EthState, error) { +// path := fmt.Sprintf( +// "%s/ext/%s/C/rpc", +// uri, +// constants.ChainAliasPrefix, +// ) +// client, err := ethclient.Dial(path) +// if err != nil { +// return nil, err +// } + +// accounts := make(map[common.Address]*c.Account, addrs.Len()) +// for addr := range addrs { +// balance, err := client.BalanceAt(ctx, addr, nil) +// if err != nil { +// return nil, err +// } +// nonce, err := client.NonceAt(ctx, addr, nil) +// if err != nil { +// return nil, err +// } +// accounts[addr] = &c.Account{ +// Balance: balance, +// Nonce: nonce, +// } +// } +// return &EthState{ +// Client: client, +// Accounts: accounts, +// }, nil +// } // AddAllUTXOs fetches all the UTXOs referenced by [addresses] that were sent // from [sourceChainID] to [destinationChainID] from the [client]. It then uses diff --git a/wallet/subnet/primary/example_test.go b/wallet/subnet/primary/example_test.go index 483c049d4ac0..4a73e8c070b2 100644 --- a/wallet/subnet/primary/example_test.go +++ b/wallet/subnet/primary/example_test.go @@ -30,7 +30,7 @@ func ExampleWallet() { wallet, err := MakeWallet(ctx, &WalletConfig{ URI: LocalAPIURI, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet with: %s\n", err) diff --git a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go index d5e8ce422307..21c081d2982b 100644 --- a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go @@ -46,9 +46,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/add-primary-validator/main.go b/wallet/subnet/primary/examples/add-primary-validator/main.go index a56dae23db3a..13c28f995f63 100644 --- a/wallet/subnet/primary/examples/add-primary-validator/main.go +++ b/wallet/subnet/primary/examples/add-primary-validator/main.go @@ -45,7 +45,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/c-chain-export/main.go b/wallet/subnet/primary/examples/c-chain-export/main.go index fec55c899feb..a6b9a0c810b8 100644 --- a/wallet/subnet/primary/examples/c-chain-export/main.go +++ b/wallet/subnet/primary/examples/c-chain-export/main.go @@ -3,70 +3,70 @@ package main -import ( - "context" - "log" - "time" +// import ( +// "context" +// "log" +// "time" - "github.com/ava-labs/avalanchego/genesis" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary" -) +// "github.com/ava-labs/avalanchego/genesis" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary" +// ) -func main() { - key := genesis.EWOQKey - uri := primary.LocalAPIURI - kc := secp256k1fx.NewKeychain(key) - avaxAddr := key.Address() +// func main() { +// key := genesis.EWOQKey +// uri := primary.LocalAPIURI +// kc := secp256k1fx.NewKeychain(key) +// avaxAddr := key.Address() - ctx := context.Background() +// ctx := context.Background() - // MakeWallet fetches the available UTXOs owned by [kc] on the network that - // [uri] is hosting. - walletSyncStartTime := time.Now() - wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, - }) - if err != nil { - log.Fatalf("failed to initialize wallet: %s\n", err) - } - log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) +// // MakeWallet fetches the available UTXOs owned by [kc] on the network that +// // [uri] is hosting. +// walletSyncStartTime := time.Now() +// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ +// URI: uri, +// AVAXKeychain: kc, +// EthKeychain: kc, +// }) +// if err != nil { +// log.Fatalf("failed to initialize wallet: %s\n", err) +// } +// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) - // Get the P-chain wallet - pWallet := wallet.P() - cWallet := wallet.C() +// // Get the P-chain wallet +// pWallet := wallet.P() +// cWallet := wallet.C() - // Pull out useful constants to use when issuing transactions. - cChainID := cWallet.BlockchainID() - owner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - avaxAddr, - }, - } +// // Pull out useful constants to use when issuing transactions. +// cChainID := cWallet.BlockchainID() +// owner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// avaxAddr, +// }, +// } - exportStartTime := time.Now() - exportTx, err := cWallet.IssueExportTx( - constants.PlatformChainID, - []*secp256k1fx.TransferOutput{{ - Amt: units.Avax, - OutputOwners: owner, - }}, - ) - if err != nil { - log.Fatalf("failed to issue export transaction: %s\n", err) - } - log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) +// exportStartTime := time.Now() +// exportTx, err := cWallet.IssueExportTx( +// constants.PlatformChainID, +// []*secp256k1fx.TransferOutput{{ +// Amt: units.Avax, +// OutputOwners: owner, +// }}, +// ) +// if err != nil { +// log.Fatalf("failed to issue export transaction: %s\n", err) +// } +// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) - importStartTime := time.Now() - importTx, err := pWallet.IssueImportTx(cChainID, &owner) - if err != nil { - log.Fatalf("failed to issue import transaction: %s\n", err) - } - log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) -} +// importStartTime := time.Now() +// importTx, err := pWallet.IssueImportTx(cChainID, &owner) +// if err != nil { +// log.Fatalf("failed to issue import transaction: %s\n", err) +// } +// log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) +// } diff --git a/wallet/subnet/primary/examples/c-chain-import/main.go b/wallet/subnet/primary/examples/c-chain-import/main.go index b4dc4e603eb3..2d9b8a244cb0 100644 --- a/wallet/subnet/primary/examples/c-chain-import/main.go +++ b/wallet/subnet/primary/examples/c-chain-import/main.go @@ -3,75 +3,75 @@ package main -import ( - "context" - "log" - "time" +// import ( +// "context" +// "log" +// "time" - "github.com/ava-labs/coreth/plugin/evm" +// "github.com/ava-labs/coreth/plugin/evm" - "github.com/ava-labs/avalanchego/genesis" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary" -) +// "github.com/ava-labs/avalanchego/genesis" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary" +// ) -func main() { - key := genesis.EWOQKey - uri := primary.LocalAPIURI - kc := secp256k1fx.NewKeychain(key) - avaxAddr := key.Address() - ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) +// func main() { +// key := genesis.EWOQKey +// uri := primary.LocalAPIURI +// kc := secp256k1fx.NewKeychain(key) +// avaxAddr := key.Address() +// ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) - ctx := context.Background() +// ctx := context.Background() - // MakeWallet fetches the available UTXOs owned by [kc] on the network that - // [uri] is hosting. - walletSyncStartTime := time.Now() - wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, - }) - if err != nil { - log.Fatalf("failed to initialize wallet: %s\n", err) - } - log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) +// // MakeWallet fetches the available UTXOs owned by [kc] on the network that +// // [uri] is hosting. +// walletSyncStartTime := time.Now() +// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ +// URI: uri, +// AVAXKeychain: kc, +// EthKeychain: kc, +// }) +// if err != nil { +// log.Fatalf("failed to initialize wallet: %s\n", err) +// } +// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) - // Get the P-chain wallet - pWallet := wallet.P() - cWallet := wallet.C() +// // Get the P-chain wallet +// pWallet := wallet.P() +// cWallet := wallet.C() - // Pull out useful constants to use when issuing transactions. - cChainID := cWallet.BlockchainID() - avaxAssetID := cWallet.AVAXAssetID() - owner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - avaxAddr, - }, - } +// // Pull out useful constants to use when issuing transactions. +// cChainID := cWallet.BlockchainID() +// avaxAssetID := cWallet.AVAXAssetID() +// owner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// avaxAddr, +// }, +// } - exportStartTime := time.Now() - exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ - Asset: avax.Asset{ID: avaxAssetID}, - Out: &secp256k1fx.TransferOutput{ - Amt: units.Avax, - OutputOwners: owner, - }, - }}) - if err != nil { - log.Fatalf("failed to issue export transaction: %s\n", err) - } - log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) +// exportStartTime := time.Now() +// exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ +// Asset: avax.Asset{ID: avaxAssetID}, +// Out: &secp256k1fx.TransferOutput{ +// Amt: units.Avax, +// OutputOwners: owner, +// }, +// }}) +// if err != nil { +// log.Fatalf("failed to issue export transaction: %s\n", err) +// } +// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) - importStartTime := time.Now() - importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) - if err != nil { - log.Fatalf("failed to issue import transaction: %s\n", err) - } - log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) -} +// importStartTime := time.Now() +// importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) +// if err != nil { +// log.Fatalf("failed to issue import transaction: %s\n", err) +// } +// log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) +// } diff --git a/wallet/subnet/primary/examples/create-asset/main.go b/wallet/subnet/primary/examples/create-asset/main.go index 30804f083df6..0bccfbb5fc52 100644 --- a/wallet/subnet/primary/examples/create-asset/main.go +++ b/wallet/subnet/primary/examples/create-asset/main.go @@ -30,7 +30,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-chain/main.go b/wallet/subnet/primary/examples/create-chain/main.go index 5e6898a1b649..521a3cca53cf 100644 --- a/wallet/subnet/primary/examples/create-chain/main.go +++ b/wallet/subnet/primary/examples/create-chain/main.go @@ -41,9 +41,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/create-locked-stakeable/main.go b/wallet/subnet/primary/examples/create-locked-stakeable/main.go index e688968e9e8a..92f1b5cb0e1b 100644 --- a/wallet/subnet/primary/examples/create-locked-stakeable/main.go +++ b/wallet/subnet/primary/examples/create-locked-stakeable/main.go @@ -39,7 +39,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-subnet/main.go b/wallet/subnet/primary/examples/create-subnet/main.go index add98ea7931c..3e8d69bc016a 100644 --- a/wallet/subnet/primary/examples/create-subnet/main.go +++ b/wallet/subnet/primary/examples/create-subnet/main.go @@ -28,7 +28,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/remove-subnet-validator/main.go b/wallet/subnet/primary/examples/remove-subnet-validator/main.go index 2842c7c0a790..46f4b85124db 100644 --- a/wallet/subnet/primary/examples/remove-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/remove-subnet-validator/main.go @@ -38,9 +38,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/wallet.go b/wallet/subnet/primary/wallet.go index 54de390d029c..de50d12f866b 100644 --- a/wallet/subnet/primary/wallet.go +++ b/wallet/subnet/primary/wallet.go @@ -11,7 +11,6 @@ import ( "github.com/ava-labs/avalanchego/utils/crypto/keychain" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" @@ -23,13 +22,13 @@ var _ Wallet = (*wallet)(nil) type Wallet interface { P() p.Wallet X() x.Wallet - C() c.Wallet + // C() c.Wallet } type wallet struct { p p.Wallet x x.Wallet - c c.Wallet + // c c.Wallet } func (w *wallet) P() p.Wallet { @@ -40,16 +39,16 @@ func (w *wallet) X() x.Wallet { return w.x } -func (w *wallet) C() c.Wallet { - return w.c -} +// func (w *wallet) C() c.Wallet { +// return w.c +// } // Creates a new default wallet -func NewWallet(p p.Wallet, x x.Wallet, c c.Wallet) Wallet { +func NewWallet(p p.Wallet, x x.Wallet /*, c c.Wallet*/) Wallet { return &wallet{ p: p, x: x, - c: c, + // c: c, } } @@ -58,7 +57,7 @@ func NewWalletWithOptions(w Wallet, options ...common.Option) Wallet { return NewWallet( p.NewWalletWithOptions(w.P(), options...), x.NewWalletWithOptions(w.X(), options...), - c.NewWalletWithOptions(w.C(), options...), + // c.NewWalletWithOptions(w.C(), options...), ) } @@ -67,7 +66,7 @@ type WalletConfig struct { URI string // required // Keys to use for signing all transactions. AVAXKeychain keychain.Keychain // required - EthKeychain c.EthKeychain // required + // EthKeychain c.EthKeychain // required // Set of P-chain transactions that the wallet should know about to be able // to generate transactions. PChainTxs map[ids.ID]*txs.Tx // optional @@ -93,11 +92,11 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { return nil, err } - ethAddrs := config.EthKeychain.EthAddresses() - ethState, err := FetchEthState(ctx, config.URI, ethAddrs) - if err != nil { - return nil, err - } + // ethAddrs := config.EthKeychain.EthAddresses() + // ethState, err := FetchEthState(ctx, config.URI, ethAddrs) + // if err != nil { + // return nil, err + // } pChainTxs := config.PChainTxs if pChainTxs == nil { @@ -127,15 +126,15 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { xBuilder := x.NewBuilder(avaxAddrs, xBackend) xSigner := x.NewSigner(config.AVAXKeychain, xBackend) - cChainID := avaxState.CCTX.BlockchainID() - cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) - cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) - cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) - cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) + // cChainID := avaxState.CCTX.BlockchainID() + // cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) + // cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) + // cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) + // cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) return NewWallet( p.NewWallet(pBuilder, pSigner, avaxState.PClient, pBackend), x.NewWallet(xBuilder, xSigner, avaxState.XClient, xBackend), - c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), + // c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), ), nil } From 36f700a3b1dfb635a95b8e9a8d69605f88021374 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 2 Nov 2023 19:25:25 +0100 Subject: [PATCH 28/36] bumped coreth version --- go.mod | 25 + go.sum | 76 ++ node/node.go | 4 +- tests/e2e/c/dynamic_fees.go | 326 +++---- tests/e2e/c/interchain_workflow.go | 320 +++---- tests/e2e/e2e.go | 116 +-- tests/e2e/p/interchain_workflow.go | 444 +++++----- tests/e2e/x/interchain_workflow.go | 296 +++---- tests/fixture/testnet/config.go | 54 +- vms/example/xsvm/cmd/chain/create/cmd.go | 6 +- wallet/chain/c/backend.go | 300 +++---- wallet/chain/c/builder.go | 792 +++++++++--------- wallet/chain/c/builder_with_options.go | 136 +-- wallet/chain/c/context.go | 130 +-- wallet/chain/c/signer.go | 436 +++++----- wallet/chain/c/wallet.go | 402 ++++----- wallet/chain/c/wallet_with_options.go | 134 +-- wallet/subnet/primary/api.go | 119 +-- wallet/subnet/primary/example_test.go | 2 +- .../add-permissioned-subnet-validator/main.go | 6 +- .../examples/add-primary-validator/main.go | 2 +- .../primary/examples/c-chain-export/main.go | 118 +-- .../primary/examples/c-chain-import/main.go | 126 +-- .../primary/examples/create-asset/main.go | 2 +- .../primary/examples/create-chain/main.go | 6 +- .../examples/create-locked-stakeable/main.go | 2 +- .../primary/examples/create-subnet/main.go | 2 +- .../examples/remove-subnet-validator/main.go | 6 +- wallet/subnet/primary/wallet.go | 41 +- 29 files changed, 2275 insertions(+), 2154 deletions(-) diff --git a/go.mod b/go.mod index 40d59d0cb294..3f8ced8be60e 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/DataDog/zstd v1.5.2 github.com/Microsoft/go-winio v0.5.2 github.com/NYTimes/gziphandler v1.1.1 + github.com/ava-labs/coreth v0.12.8-rc.1.0.20231102183021-48a940d8af8f github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 github.com/btcsuite/btcd/btcutil v1.1.3 github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 @@ -71,6 +72,7 @@ require ( require ( github.com/BurntSushi/toml v1.2.1 // indirect + github.com/VictoriaMetrics/fastcache v1.10.0 // indirect github.com/benbjohnson/clock v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect @@ -79,26 +81,44 @@ require ( github.com/cockroachdb/errors v1.9.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/redact v1.1.3 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set/v2 v2.1.0 // indirect + github.com/dlclark/regexp2 v1.7.0 // indirect + github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect + github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/frankban/quicktest v1.14.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect + github.com/go-stack/stack v1.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/go-cmp v0.5.9 // indirect + github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 // indirect + github.com/hashicorp/go-bexpr v0.1.10 // indirect + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/klauspost/compress v1.15.15 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/magiconair/properties v1.8.6 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mitchellh/pointerstructure v1.2.0 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect @@ -106,12 +126,17 @@ require ( github.com/prometheus/common v0.39.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sanity-io/litter v1.5.1 // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/status-im/keycard-go v0.2.0 // indirect github.com/subosito/gotenv v1.3.0 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/zondax/hid v0.9.1 // indirect github.com/zondax/ledger-go v0.14.1 // indirect diff --git a/go.sum b/go.sum index 09e5526b3f20..eb81f62cc522 100644 --- a/go.sum +++ b/go.sum @@ -52,12 +52,18 @@ github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cq github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= +github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY= +github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/ava-labs/coreth v0.12.8-rc.1.0.20231102183021-48a940d8af8f h1:ooUmGkbVexlJOv4A3MSbC6lkJcuCzVaisKNmRdZHfpU= +github.com/ava-labs/coreth v0.12.8-rc.1.0.20231102183021-48a940d8af8f/go.mod h1:rxwLS9SRXjAVz2+v9oIdUzTwNTLRAfvY5b3wZlF1s/s= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7 h1:EdxD90j5sClfL5Ngpz2TlnbnkNYdFPDXa0jDOjam65c= github.com/ava-labs/ledger-avalanche/go v0.0.0-20230105152938-00a24d05a8c7/go.mod h1:XhiXSrh90sHUbkERzaxEftCmUz53eCijshDLZ4fByVM= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= @@ -94,13 +100,18 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -130,12 +141,16 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= +github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= @@ -146,6 +161,14 @@ github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6ps github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= +github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= +github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= +github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -162,6 +185,8 @@ github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2 github.com/ethereum/go-ethereum v1.12.0/go.mod h1:/oo2X/dZLJjf2mJ6YT9wcWxa4nNJDBKDBU6sFIpx1Gs= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -170,6 +195,8 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= @@ -193,7 +220,11 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= @@ -278,10 +309,14 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -302,11 +337,17 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 h1:kr3j8iIMR4ywO/O0rvksXaJvauGGCMg2zAZIiNZ9uIQ= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0/go.mod h1:ummNFgdgLhhX7aIiy35vVmQNS0rWXknfPE0qe6fmFXg= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw= +github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e/go.mod h1:j9cQbcqHQujT0oKJ38PylVfqohClLr3CvDC+Qcg+lhU= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8= @@ -318,6 +359,7 @@ github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3 github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -359,6 +401,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -366,6 +409,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= @@ -376,11 +420,17 @@ github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -389,8 +439,11 @@ github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -409,6 +462,8 @@ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -476,6 +531,8 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sanity-io/litter v1.5.1 h1:dwnrSypP6q56o3lFxTU+t2fwQ9A+U5qrXVO4Qg9KwVU= github.com/sanity-io/litter v1.5.1/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0= @@ -511,6 +568,8 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= +github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -540,10 +599,14 @@ github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITn github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= +github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -555,6 +618,8 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1: github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= @@ -564,6 +629,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= @@ -661,6 +727,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -706,6 +773,7 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -729,6 +797,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -793,8 +862,12 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -811,6 +884,7 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -874,6 +948,7 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -998,6 +1073,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= diff --git a/node/node.go b/node/node.go index f12d591d5ccf..cad0073899b8 100644 --- a/node/node.go +++ b/node/node.go @@ -25,7 +25,7 @@ import ( "go.uber.org/zap" - // coreth "github.com/ava-labs/coreth/plugin/evm" + coreth "github.com/ava-labs/coreth/plugin/evm" "github.com/ava-labs/avalanchego/api/admin" "github.com/ava-labs/avalanchego/api/auth" @@ -940,7 +940,7 @@ func (n *Node) initVMs() error { CreateAssetTxFee: n.Config.CreateAssetTxFee, }, }), - // vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), + vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), n.VMManager.RegisterFactory(context.TODO(), secp256k1fx.ID, &secp256k1fx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), nftfx.ID, &nftfx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), propertyfx.ID, &propertyfx.Factory{}), diff --git a/tests/e2e/c/dynamic_fees.go b/tests/e2e/c/dynamic_fees.go index 779c8670be37..edfbef2671a8 100644 --- a/tests/e2e/c/dynamic_fees.go +++ b/tests/e2e/c/dynamic_fees.go @@ -3,166 +3,166 @@ package c -// import ( -// "math/big" -// "strings" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/stretchr/testify/require" - -// "github.com/ethereum/go-ethereum/accounts/abi" -// "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/coreth/core/types" -// "github.com/ava-labs/coreth/params" -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/tests" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/tests/fixture/testnet" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// ) - -// // This test uses the compiled bin for `hashing.sol` as -// // well as its ABI contained in `hashing_contract.go`. - -// var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { -// require := require.New(ginkgo.GinkgoT()) - -// // Need a gas limit much larger than the standard 21_000 to enable -// // the contract to induce a gas price increase -// const largeGasLimit = uint64(8_000_000) - -// // TODO(marun) What is the significance of this value? -// gasTip := big.NewInt(1000 * params.GWei) - -// ginkgo.It("should ensure that the gas price is affected by load", func() { -// ginkgo.By("creating a new private network to ensure isolation from other tests") -// privateNetwork := e2e.Env.NewPrivateNetwork() - -// ginkgo.By("allocating a pre-funded key") -// key := privateNetwork.GetConfig().FundedKeys[0] -// ethAddress := evm.GetEthAddress(key) - -// ginkgo.By("initializing a coreth client") -// node := privateNetwork.GetNodes()[0] -// nodeURI := testnet.NodeURI{ -// NodeID: node.GetID(), -// URI: node.GetProcessContext().URI, -// } -// ethClient := e2e.Env.NewEthClient(nodeURI) - -// ginkgo.By("initializing a transaction signer") -// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) -// require.NoError(err) -// signer := types.NewEIP155Signer(cChainID) -// ecdsaKey := key.ToECDSA() -// sign := func(tx *types.Transaction) *types.Transaction { -// signedTx, err := types.SignTx(tx, signer, ecdsaKey) -// require.NoError(err) -// return signedTx -// } - -// var contractAddress common.Address -// ginkgo.By("deploying an expensive contract", func() { -// // Create transaction -// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) -// require.NoError(err) -// compiledContract := common.Hex2Bytes(hashingCompiledContract) -// tx := types.NewTx(&types.LegacyTx{ -// Nonce: nonce, -// GasPrice: gasTip, -// Gas: largeGasLimit, -// Value: common.Big0, -// Data: compiledContract, -// }) - -// // Send the transaction and wait for acceptance -// signedTx := sign(tx) -// receipt := e2e.SendEthTransaction(ethClient, signedTx) - -// contractAddress = receipt.ContractAddress -// }) - -// var gasPrice *big.Int -// ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { -// // Evaluate the bytes representation of the contract -// hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) -// require.NoError(err) -// contractData, err := hashingABI.Pack("hashIt") -// require.NoError(err) - -// var initialGasPrice *big.Int -// e2e.Eventually(func() bool { -// // Check the gas price -// var err error -// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) -// require.NoError(err) -// if initialGasPrice == nil { -// initialGasPrice = gasPrice -// tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) -// } else if gasPrice.Cmp(initialGasPrice) > 0 { -// // Gas price has increased -// tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) -// return true -// } - -// // Create the transaction -// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) -// require.NoError(err) -// tx := types.NewTx(&types.LegacyTx{ -// Nonce: nonce, -// GasPrice: gasTip, -// Gas: largeGasLimit, -// To: &contractAddress, -// Value: common.Big0, -// Data: contractData, -// }) - -// // Send the transaction and wait for acceptance -// signedTx := sign(tx) -// _ = e2e.SendEthTransaction(ethClient, signedTx) - -// // The gas price will be checked at the start of the next iteration -// return false -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") -// }) - -// ginkgo.By("waiting for the gas price to decrease...", func() { -// initialGasPrice := gasPrice -// e2e.Eventually(func() bool { -// var err error -// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) -// require.NoError(err) -// tests.Outf("{{blue}}.{{/}}") -// return initialGasPrice.Cmp(gasPrice) > 0 -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") -// tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) -// }) - -// ginkgo.By("sending funds at the current gas price", func() { -// // Create a recipient address -// recipientKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) -// recipientEthAddress := evm.GetEthAddress(recipientKey) - -// // Create transaction -// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) -// require.NoError(err) -// tx := types.NewTx(&types.LegacyTx{ -// Nonce: nonce, -// GasPrice: gasPrice, -// Gas: e2e.DefaultGasLimit, -// To: &recipientEthAddress, -// Value: common.Big0, -// }) - -// // Send the transaction and wait for acceptance -// signedTx := sign(tx) -// _ = e2e.SendEthTransaction(ethClient, signedTx) -// }) - -// e2e.CheckBootstrapIsPossible(privateNetwork) -// }) -// }) +import ( + "math/big" + "strings" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/coreth/params" + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/tests" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/tests/fixture/testnet" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +) + +// This test uses the compiled bin for `hashing.sol` as +// well as its ABI contained in `hashing_contract.go`. + +var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { + require := require.New(ginkgo.GinkgoT()) + + // Need a gas limit much larger than the standard 21_000 to enable + // the contract to induce a gas price increase + const largeGasLimit = uint64(8_000_000) + + // TODO(marun) What is the significance of this value? + gasTip := big.NewInt(1000 * params.GWei) + + ginkgo.It("should ensure that the gas price is affected by load", func() { + ginkgo.By("creating a new private network to ensure isolation from other tests") + privateNetwork := e2e.Env.NewPrivateNetwork() + + ginkgo.By("allocating a pre-funded key") + key := privateNetwork.GetConfig().FundedKeys[0] + ethAddress := evm.GetEthAddress(key) + + ginkgo.By("initializing a coreth client") + node := privateNetwork.GetNodes()[0] + nodeURI := testnet.NodeURI{ + NodeID: node.GetID(), + URI: node.GetProcessContext().URI, + } + ethClient := e2e.Env.NewEthClient(nodeURI) + + ginkgo.By("initializing a transaction signer") + cChainID, err := ethClient.ChainID(e2e.DefaultContext()) + require.NoError(err) + signer := types.NewEIP155Signer(cChainID) + ecdsaKey := key.ToECDSA() + sign := func(tx *types.Transaction) *types.Transaction { + signedTx, err := types.SignTx(tx, signer, ecdsaKey) + require.NoError(err) + return signedTx + } + + var contractAddress common.Address + ginkgo.By("deploying an expensive contract", func() { + // Create transaction + nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) + require.NoError(err) + compiledContract := common.Hex2Bytes(hashingCompiledContract) + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + GasPrice: gasTip, + Gas: largeGasLimit, + Value: common.Big0, + Data: compiledContract, + }) + + // Send the transaction and wait for acceptance + signedTx := sign(tx) + receipt := e2e.SendEthTransaction(ethClient, signedTx) + + contractAddress = receipt.ContractAddress + }) + + var gasPrice *big.Int + ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { + // Evaluate the bytes representation of the contract + hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) + require.NoError(err) + contractData, err := hashingABI.Pack("hashIt") + require.NoError(err) + + var initialGasPrice *big.Int + e2e.Eventually(func() bool { + // Check the gas price + var err error + gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) + require.NoError(err) + if initialGasPrice == nil { + initialGasPrice = gasPrice + tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) + } else if gasPrice.Cmp(initialGasPrice) > 0 { + // Gas price has increased + tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) + return true + } + + // Create the transaction + nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) + require.NoError(err) + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + GasPrice: gasTip, + Gas: largeGasLimit, + To: &contractAddress, + Value: common.Big0, + Data: contractData, + }) + + // Send the transaction and wait for acceptance + signedTx := sign(tx) + _ = e2e.SendEthTransaction(ethClient, signedTx) + + // The gas price will be checked at the start of the next iteration + return false + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") + }) + + ginkgo.By("waiting for the gas price to decrease...", func() { + initialGasPrice := gasPrice + e2e.Eventually(func() bool { + var err error + gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) + require.NoError(err) + tests.Outf("{{blue}}.{{/}}") + return initialGasPrice.Cmp(gasPrice) > 0 + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") + tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) + }) + + ginkgo.By("sending funds at the current gas price", func() { + // Create a recipient address + recipientKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + recipientEthAddress := evm.GetEthAddress(recipientKey) + + // Create transaction + nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) + require.NoError(err) + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + GasPrice: gasPrice, + Gas: e2e.DefaultGasLimit, + To: &recipientEthAddress, + Value: common.Big0, + }) + + // Send the transaction and wait for acceptance + signedTx := sign(tx) + _ = e2e.SendEthTransaction(ethClient, signedTx) + }) + + e2e.CheckBootstrapIsPossible(privateNetwork) + }) +}) diff --git a/tests/e2e/c/interchain_workflow.go b/tests/e2e/c/interchain_workflow.go index d13c4b8db1ce..8bed85eb1bd9 100644 --- a/tests/e2e/c/interchain_workflow.go +++ b/tests/e2e/c/interchain_workflow.go @@ -3,163 +3,163 @@ package c -// import ( -// "math/big" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/stretchr/testify/require" - -// "github.com/ava-labs/coreth/core/types" -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { -// require := require.New(ginkgo.GinkgoT()) - -// const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer - -// ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { -// ginkgo.By("initializing a new eth client") -// // Select a random node URI to use for both the eth client and -// // the wallet to avoid having to verify that all nodes are at -// // the same height before initializing the wallet. -// nodeURI := e2e.Env.GetRandomNodeURI() -// ethClient := e2e.Env.NewEthClient(nodeURI) - -// ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") -// senderKey := e2e.Env.AllocateFundedKey() -// senderEthAddress := evm.GetEthAddress(senderKey) -// recipientKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) -// recipientEthAddress := evm.GetEthAddress(recipientKey) - -// ginkgo.By("sending funds from one address to another on the C-Chain", func() { -// // Create transaction -// acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) -// require.NoError(err) -// gasPrice := e2e.SuggestGasPrice(ethClient) -// tx := types.NewTransaction( -// acceptedNonce, -// recipientEthAddress, -// big.NewInt(int64(txAmount)), -// e2e.DefaultGasLimit, -// gasPrice, -// nil, -// ) - -// // Sign transaction -// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) -// require.NoError(err) -// signer := types.NewEIP155Signer(cChainID) -// signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) -// require.NoError(err) - -// _ = e2e.SendEthTransaction(ethClient, signedTx) - -// ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") -// e2e.Eventually(func() bool { -// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) -// require.NoError(err) -// return balance.Cmp(big.NewInt(0)) > 0 -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") -// }) - -// // Wallet must be initialized after sending funds on the -// // C-Chain with the same node URI to ensure wallet state -// // matches on-chain state. -// ginkgo.By("initializing a keychain and associated wallet") -// keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) -// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) -// xWallet := baseWallet.X() -// cWallet := baseWallet.C() -// pWallet := baseWallet.P() - -// ginkgo.By("defining common configuration") -// avaxAssetID := xWallet.AVAXAssetID() -// // Use the same owner for import funds to X-Chain and P-Chain -// recipientOwner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// recipientKey.Address(), -// }, -// } -// // Use the same outputs for both X-Chain and P-Chain exports -// exportOutputs := []*secp256k1fx.TransferOutput{ -// { -// Amt: txAmount, -// OutputOwners: secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// keychain.Keys[0].Address(), -// }, -// }, -// }, -// } - -// ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { -// _, err := cWallet.IssueExportTx( -// xWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { -// _, err := xWallet.IssueImportTx( -// cWallet.BlockchainID(), -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { -// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { -// _, err := cWallet.IssueExportTx( -// constants.PlatformChainID, -// exportOutputs, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { -// _, err = pWallet.IssueImportTx( -// cWallet.BlockchainID(), -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { -// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) -// }) -// }) +import ( + "math/big" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { + require := require.New(ginkgo.GinkgoT()) + + const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer + + ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { + ginkgo.By("initializing a new eth client") + // Select a random node URI to use for both the eth client and + // the wallet to avoid having to verify that all nodes are at + // the same height before initializing the wallet. + nodeURI := e2e.Env.GetRandomNodeURI() + ethClient := e2e.Env.NewEthClient(nodeURI) + + ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") + senderKey := e2e.Env.AllocateFundedKey() + senderEthAddress := evm.GetEthAddress(senderKey) + recipientKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + recipientEthAddress := evm.GetEthAddress(recipientKey) + + ginkgo.By("sending funds from one address to another on the C-Chain", func() { + // Create transaction + acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) + require.NoError(err) + gasPrice := e2e.SuggestGasPrice(ethClient) + tx := types.NewTransaction( + acceptedNonce, + recipientEthAddress, + big.NewInt(int64(txAmount)), + e2e.DefaultGasLimit, + gasPrice, + nil, + ) + + // Sign transaction + cChainID, err := ethClient.ChainID(e2e.DefaultContext()) + require.NoError(err) + signer := types.NewEIP155Signer(cChainID) + signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) + require.NoError(err) + + _ = e2e.SendEthTransaction(ethClient, signedTx) + + ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") + e2e.Eventually(func() bool { + balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) + require.NoError(err) + return balance.Cmp(big.NewInt(0)) > 0 + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") + }) + + // Wallet must be initialized after sending funds on the + // C-Chain with the same node URI to ensure wallet state + // matches on-chain state. + ginkgo.By("initializing a keychain and associated wallet") + keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) + baseWallet := e2e.Env.NewWallet(keychain, nodeURI) + xWallet := baseWallet.X() + cWallet := baseWallet.C() + pWallet := baseWallet.P() + + ginkgo.By("defining common configuration") + avaxAssetID := xWallet.AVAXAssetID() + // Use the same owner for import funds to X-Chain and P-Chain + recipientOwner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + recipientKey.Address(), + }, + } + // Use the same outputs for both X-Chain and P-Chain exports + exportOutputs := []*secp256k1fx.TransferOutput{ + { + Amt: txAmount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + keychain.Keys[0].Address(), + }, + }, + }, + } + + ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { + _, err := cWallet.IssueExportTx( + xWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { + _, err := xWallet.IssueImportTx( + cWallet.BlockchainID(), + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { + balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { + _, err := cWallet.IssueExportTx( + constants.PlatformChainID, + exportOutputs, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { + _, err = pWallet.IssueImportTx( + cWallet.BlockchainID(), + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { + balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) + }) +}) diff --git a/tests/e2e/e2e.go b/tests/e2e/e2e.go index 8b70b9f9ca3f..130f33f1197c 100644 --- a/tests/e2e/e2e.go +++ b/tests/e2e/e2e.go @@ -7,15 +7,23 @@ package e2e import ( "context" "encoding/json" + "errors" + "fmt" + "math/big" "math/rand" "os" "path/filepath" + "strings" "time" ginkgo "github.com/onsi/ginkgo/v2" "github.com/stretchr/testify/require" + "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/coreth/ethclient" + "github.com/ava-labs/coreth/interfaces" + "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/tests" "github.com/ava-labs/avalanchego/tests/fixture" @@ -126,7 +134,7 @@ func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain, nodeURI tes baseWallet, err := primary.MakeWallet(DefaultContext(), &primary.WalletConfig{ URI: nodeURI.URI, AVAXKeychain: keychain, - // EthKeychain: keychain, + EthKeychain: keychain, }) te.require.NoError(err) return primary.NewWalletWithOptions( @@ -139,16 +147,16 @@ func (te *TestEnvironment) NewWallet(keychain *secp256k1fx.Keychain, nodeURI tes ) } -// // Create a new eth client targeting the specified node URI. -// // TODO(marun) Make this a regular function. -// func (te *TestEnvironment) NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { -// tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) -// nodeAddress := strings.Split(nodeURI.URI, "//")[1] -// uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) -// client, err := ethclient.Dial(uri) -// te.require.NoError(err) -// return client -// } +// Create a new eth client targeting the specified node URI. +// TODO(marun) Make this a regular function. +func (te *TestEnvironment) NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { + tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) + nodeAddress := strings.Split(nodeURI.URI, "//")[1] + uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) + client, err := ethclient.Dial(uri) + te.require.NoError(err) + return client +} // Create a new private network that is not shared with other tests. func (te *TestEnvironment) NewPrivateNetwork() testnet.Network { @@ -223,49 +231,49 @@ func WaitForHealthy(node testnet.Node) { require.NoError(ginkgo.GinkgoT(), testnet.WaitForHealthy(DefaultContext(), node)) } -// // Sends an eth transaction, waits for the transaction receipt to be issued -// // and checks that the receipt indicates success. -// func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { -// require := require.New(ginkgo.GinkgoT()) - -// txID := signedTx.Hash() -// tests.Outf(" sending eth transaction with ID: %s\n", txID) - -// require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) - -// // Wait for the receipt -// var receipt *types.Receipt -// Eventually(func() bool { -// var err error -// receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) -// if errors.Is(err, interfaces.NotFound) { -// return false // Transaction is still pending -// } -// require.NoError(err) -// return true -// }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") - -// require.Equal(receipt.Status, types.ReceiptStatusSuccessful) -// return receipt -// } - -// // Determines the suggested gas price for the configured client that will -// // maximize the chances of transaction acceptance. -// func SuggestGasPrice(ethClient ethclient.Client) *big.Int { -// gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) -// require.NoError(ginkgo.GinkgoT(), err) -// // Double the suggested gas price to maximize the chances of -// // acceptance. Maybe this can be revisited pending resolution of -// // https://github.com/ava-labs/coreth/issues/314. -// gasPrice.Add(gasPrice, gasPrice) -// return gasPrice -// } - -// // Helper simplifying use via an option of a gas price appropriate for testing. -// func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { -// baseFee := SuggestGasPrice(ethClient) -// return common.WithBaseFee(baseFee) -// } +// Sends an eth transaction, waits for the transaction receipt to be issued +// and checks that the receipt indicates success. +func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { + require := require.New(ginkgo.GinkgoT()) + + txID := signedTx.Hash() + tests.Outf(" sending eth transaction with ID: %s\n", txID) + + require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) + + // Wait for the receipt + var receipt *types.Receipt + Eventually(func() bool { + var err error + receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) + if errors.Is(err, interfaces.NotFound) { + return false // Transaction is still pending + } + require.NoError(err) + return true + }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") + + require.Equal(receipt.Status, types.ReceiptStatusSuccessful) + return receipt +} + +// Determines the suggested gas price for the configured client that will +// maximize the chances of transaction acceptance. +func SuggestGasPrice(ethClient ethclient.Client) *big.Int { + gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) + require.NoError(ginkgo.GinkgoT(), err) + // Double the suggested gas price to maximize the chances of + // acceptance. Maybe this can be revisited pending resolution of + // https://github.com/ava-labs/coreth/issues/314. + gasPrice.Add(gasPrice, gasPrice) + return gasPrice +} + +// Helper simplifying use via an option of a gas price appropriate for testing. +func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { + baseFee := SuggestGasPrice(ethClient) + return common.WithBaseFee(baseFee) +} // Verify that a new node can bootstrap into the network. func CheckBootstrapIsPossible(network testnet.Network) { diff --git a/tests/e2e/p/interchain_workflow.go b/tests/e2e/p/interchain_workflow.go index d3715c254e90..729418adbd97 100644 --- a/tests/e2e/p/interchain_workflow.go +++ b/tests/e2e/p/interchain_workflow.go @@ -3,225 +3,225 @@ package p -// import ( -// "math/big" -// "time" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/spf13/cast" - -// "github.com/stretchr/testify/require" - -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/api/info" -// "github.com/ava-labs/avalanchego/config" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/tests/fixture/testnet" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/platformvm/reward" -// "github.com/ava-labs/avalanchego/vms/platformvm/txs" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { -// require := require.New(ginkgo.GinkgoT()) - -// const ( -// transferAmount = 10 * units.Avax -// weight = 2_000 * units.Avax // Used for both validation and delegation -// ) - -// ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { -// network := e2e.Env.GetNetwork() - -// ginkgo.By("checking that the network has a compatible minimum stake duration", func() { -// minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) -// require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) -// }) - -// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") -// recipientKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) -// keychain := e2e.Env.NewKeychain(1) -// keychain.Add(recipientKey) -// nodeURI := e2e.Env.GetRandomNodeURI() -// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) -// xWallet := baseWallet.X() -// cWallet := baseWallet.C() -// pWallet := baseWallet.P() - -// ginkgo.By("defining common configuration") -// recipientEthAddress := evm.GetEthAddress(recipientKey) -// avaxAssetID := xWallet.AVAXAssetID() -// // Use the same owner for sending to X-Chain and importing funds to P-Chain -// recipientOwner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// recipientKey.Address(), -// }, -// } -// // Use the same outputs for both X-Chain and C-Chain exports -// exportOutputs := []*avax.TransferableOutput{ -// { -// Asset: avax.Asset{ -// ID: avaxAssetID, -// }, -// Out: &secp256k1fx.TransferOutput{ -// Amt: transferAmount, -// OutputOwners: secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// keychain.Keys[0].Address(), -// }, -// }, -// }, -// }, -// } - -// ginkgo.By("adding new node and waiting for it to report healthy") -// node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) -// e2e.WaitForHealthy(node) - -// ginkgo.By("retrieving new node's id and pop") -// infoClient := info.NewClient(node.GetProcessContext().URI) -// nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) -// require.NoError(err) - -// ginkgo.By("adding the new node as a validator", func() { -// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) -// // Validation duration doesn't actually matter to this -// // test - it is only ensuring that adding a validator -// // doesn't break interchain transfer. -// endTime := startTime.Add(30 * time.Second) - -// rewardKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) - -// const ( -// delegationPercent = 0.10 // 10% -// delegationShare = reward.PercentDenominator * delegationPercent -// ) - -// _, err = pWallet.IssueAddPermissionlessValidatorTx( -// &txs.SubnetValidator{ -// Validator: txs.Validator{ -// NodeID: nodeID, -// Start: uint64(startTime.Unix()), -// End: uint64(endTime.Unix()), -// Wght: weight, -// }, -// Subnet: constants.PrimaryNetworkID, -// }, -// nodePOP, -// pWallet.AVAXAssetID(), -// &secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{rewardKey.Address()}, -// }, -// &secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{rewardKey.Address()}, -// }, -// delegationShare, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("adding a delegator to the new node", func() { -// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) -// // Delegation duration doesn't actually matter to this -// // test - it is only ensuring that adding a delegator -// // doesn't break interchain transfer. -// endTime := startTime.Add(15 * time.Second) - -// rewardKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) - -// _, err = pWallet.IssueAddPermissionlessDelegatorTx( -// &txs.SubnetValidator{ -// Validator: txs.Validator{ -// NodeID: nodeID, -// Start: uint64(startTime.Unix()), -// End: uint64(endTime.Unix()), -// Wght: weight, -// }, -// Subnet: constants.PrimaryNetworkID, -// }, -// pWallet.AVAXAssetID(), -// &secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{rewardKey.Address()}, -// }, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { -// _, err := pWallet.IssueExportTx( -// xWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { -// _, err := xWallet.IssueImportTx( -// constants.PlatformChainID, -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { -// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { -// _, err := pWallet.IssueExportTx( -// cWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("initializing a new eth client") -// ethClient := e2e.Env.NewEthClient(nodeURI) - -// ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { -// _, err := cWallet.IssueImportTx( -// constants.PlatformChainID, -// recipientEthAddress, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") -// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) -// require.NoError(err) -// require.Positive(balance.Cmp(big.NewInt(0))) - -// ginkgo.By("stopping validator node to free up resources for a bootstrap check") -// require.NoError(node.Stop()) - -// e2e.CheckBootstrapIsPossible(network) -// }) -// }) +import ( + "math/big" + "time" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/spf13/cast" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/api/info" + "github.com/ava-labs/avalanchego/config" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/tests/fixture/testnet" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/platformvm/reward" + "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { + require := require.New(ginkgo.GinkgoT()) + + const ( + transferAmount = 10 * units.Avax + weight = 2_000 * units.Avax // Used for both validation and delegation + ) + + ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { + network := e2e.Env.GetNetwork() + + ginkgo.By("checking that the network has a compatible minimum stake duration", func() { + minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) + require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) + }) + + ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") + recipientKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + keychain := e2e.Env.NewKeychain(1) + keychain.Add(recipientKey) + nodeURI := e2e.Env.GetRandomNodeURI() + baseWallet := e2e.Env.NewWallet(keychain, nodeURI) + xWallet := baseWallet.X() + cWallet := baseWallet.C() + pWallet := baseWallet.P() + + ginkgo.By("defining common configuration") + recipientEthAddress := evm.GetEthAddress(recipientKey) + avaxAssetID := xWallet.AVAXAssetID() + // Use the same owner for sending to X-Chain and importing funds to P-Chain + recipientOwner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + recipientKey.Address(), + }, + } + // Use the same outputs for both X-Chain and C-Chain exports + exportOutputs := []*avax.TransferableOutput{ + { + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: transferAmount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + keychain.Keys[0].Address(), + }, + }, + }, + }, + } + + ginkgo.By("adding new node and waiting for it to report healthy") + node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) + e2e.WaitForHealthy(node) + + ginkgo.By("retrieving new node's id and pop") + infoClient := info.NewClient(node.GetProcessContext().URI) + nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) + require.NoError(err) + + ginkgo.By("adding the new node as a validator", func() { + startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) + // Validation duration doesn't actually matter to this + // test - it is only ensuring that adding a validator + // doesn't break interchain transfer. + endTime := startTime.Add(30 * time.Second) + + rewardKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + + const ( + delegationPercent = 0.10 // 10% + delegationShare = reward.PercentDenominator * delegationPercent + ) + + _, err = pWallet.IssueAddPermissionlessValidatorTx( + &txs.SubnetValidator{ + Validator: txs.Validator{ + NodeID: nodeID, + Start: uint64(startTime.Unix()), + End: uint64(endTime.Unix()), + Wght: weight, + }, + Subnet: constants.PrimaryNetworkID, + }, + nodePOP, + pWallet.AVAXAssetID(), + &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{rewardKey.Address()}, + }, + &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{rewardKey.Address()}, + }, + delegationShare, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("adding a delegator to the new node", func() { + startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) + // Delegation duration doesn't actually matter to this + // test - it is only ensuring that adding a delegator + // doesn't break interchain transfer. + endTime := startTime.Add(15 * time.Second) + + rewardKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + + _, err = pWallet.IssueAddPermissionlessDelegatorTx( + &txs.SubnetValidator{ + Validator: txs.Validator{ + NodeID: nodeID, + Start: uint64(startTime.Unix()), + End: uint64(endTime.Unix()), + Wght: weight, + }, + Subnet: constants.PrimaryNetworkID, + }, + pWallet.AVAXAssetID(), + &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{rewardKey.Address()}, + }, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { + _, err := pWallet.IssueExportTx( + xWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { + _, err := xWallet.IssueImportTx( + constants.PlatformChainID, + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { + balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { + _, err := pWallet.IssueExportTx( + cWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("initializing a new eth client") + ethClient := e2e.Env.NewEthClient(nodeURI) + + ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { + _, err := cWallet.IssueImportTx( + constants.PlatformChainID, + recipientEthAddress, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") + balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) + require.NoError(err) + require.Positive(balance.Cmp(big.NewInt(0))) + + ginkgo.By("stopping validator node to free up resources for a bootstrap check") + require.NoError(node.Stop()) + + e2e.CheckBootstrapIsPossible(network) + }) +}) diff --git a/tests/e2e/x/interchain_workflow.go b/tests/e2e/x/interchain_workflow.go index 3b7a4c988405..6d335199b5b9 100644 --- a/tests/e2e/x/interchain_workflow.go +++ b/tests/e2e/x/interchain_workflow.go @@ -3,151 +3,151 @@ package x -// import ( -// "math/big" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/stretchr/testify/require" - -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { -// require := require.New(ginkgo.GinkgoT()) - -// const transferAmount = 10 * units.Avax - -// ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { -// nodeURI := e2e.Env.GetRandomNodeURI() - -// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") -// recipientKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) -// keychain := e2e.Env.NewKeychain(1) -// keychain.Add(recipientKey) -// baseWallet := e2e.Env.NewWallet(keychain, nodeURI) -// xWallet := baseWallet.X() -// cWallet := baseWallet.C() -// pWallet := baseWallet.P() - -// ginkgo.By("defining common configuration") -// recipientEthAddress := evm.GetEthAddress(recipientKey) -// avaxAssetID := xWallet.AVAXAssetID() -// // Use the same owner for sending to X-Chain and importing funds to P-Chain -// recipientOwner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// recipientKey.Address(), -// }, -// } -// // Use the same outputs for both C-Chain and P-Chain exports -// exportOutputs := []*avax.TransferableOutput{ -// { -// Asset: avax.Asset{ -// ID: avaxAssetID, -// }, -// Out: &secp256k1fx.TransferOutput{ -// Amt: transferAmount, -// OutputOwners: secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// keychain.Keys[0].Address(), -// }, -// }, -// }, -// }, -// } - -// ginkgo.By("sending funds from one address to another on the X-Chain", func() { -// _, err = xWallet.IssueBaseTx( -// []*avax.TransferableOutput{{ -// Asset: avax.Asset{ -// ID: avaxAssetID, -// }, -// Out: &secp256k1fx.TransferOutput{ -// Amt: transferAmount, -// OutputOwners: recipientOwner, -// }, -// }}, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { -// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { -// _, err := xWallet.IssueExportTx( -// cWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("initializing a new eth client") -// ethClient := e2e.Env.NewEthClient(nodeURI) - -// ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { -// _, err := cWallet.IssueImportTx( -// xWallet.BlockchainID(), -// recipientEthAddress, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") -// e2e.Eventually(func() bool { -// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) -// require.NoError(err) -// return balance.Cmp(big.NewInt(0)) > 0 -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") - -// ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { -// _, err := xWallet.IssueExportTx( -// constants.PlatformChainID, -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { -// _, err := pWallet.IssueImportTx( -// xWallet.BlockchainID(), -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { -// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) -// }) -// }) +import ( + "math/big" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { + require := require.New(ginkgo.GinkgoT()) + + const transferAmount = 10 * units.Avax + + ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { + nodeURI := e2e.Env.GetRandomNodeURI() + + ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") + recipientKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + keychain := e2e.Env.NewKeychain(1) + keychain.Add(recipientKey) + baseWallet := e2e.Env.NewWallet(keychain, nodeURI) + xWallet := baseWallet.X() + cWallet := baseWallet.C() + pWallet := baseWallet.P() + + ginkgo.By("defining common configuration") + recipientEthAddress := evm.GetEthAddress(recipientKey) + avaxAssetID := xWallet.AVAXAssetID() + // Use the same owner for sending to X-Chain and importing funds to P-Chain + recipientOwner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + recipientKey.Address(), + }, + } + // Use the same outputs for both C-Chain and P-Chain exports + exportOutputs := []*avax.TransferableOutput{ + { + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: transferAmount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + keychain.Keys[0].Address(), + }, + }, + }, + }, + } + + ginkgo.By("sending funds from one address to another on the X-Chain", func() { + _, err = xWallet.IssueBaseTx( + []*avax.TransferableOutput{{ + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: transferAmount, + OutputOwners: recipientOwner, + }, + }}, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { + balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { + _, err := xWallet.IssueExportTx( + cWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("initializing a new eth client") + ethClient := e2e.Env.NewEthClient(nodeURI) + + ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { + _, err := cWallet.IssueImportTx( + xWallet.BlockchainID(), + recipientEthAddress, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") + e2e.Eventually(func() bool { + balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) + require.NoError(err) + return balance.Cmp(big.NewInt(0)) > 0 + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") + + ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { + _, err := xWallet.IssueExportTx( + constants.PlatformChainID, + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { + _, err := pWallet.IssueImportTx( + xWallet.BlockchainID(), + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { + balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) + }) +}) diff --git a/tests/fixture/testnet/config.go b/tests/fixture/testnet/config.go index 6c82db1a420f..425aa646a690 100644 --- a/tests/fixture/testnet/config.go +++ b/tests/fixture/testnet/config.go @@ -15,6 +15,10 @@ import ( "github.com/spf13/cast" + "github.com/ava-labs/coreth/core" + "github.com/ava-labs/coreth/params" + "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/avalanchego/config" "github.com/ava-labs/avalanchego/genesis" "github.com/ava-labs/avalanchego/ids" @@ -139,15 +143,15 @@ func (c *NetworkConfig) EnsureGenesis(networkID uint32, validatorIDs []ids.NodeI // Ensure pre-funded keys have arbitrary large balances on both chains to support testing xChainBalances := make(XChainBalanceMap, len(c.FundedKeys)) - // cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) - // for _, key := range c.FundedKeys { - // xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount - // cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ - // Balance: DefaultFundedKeyCChainAmount, - // } - // } - - genesis, err := NewTestGenesis(networkID, xChainBalances /*, cChainBalances*/, validatorIDs) + cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) + for _, key := range c.FundedKeys { + xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount + cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ + Balance: DefaultFundedKeyCChainAmount, + } + } + + genesis, err := NewTestGenesis(networkID, xChainBalances, cChainBalances, validatorIDs) if err != nil { return err } @@ -307,7 +311,7 @@ type XChainBalanceMap map[ids.ShortID]uint64 func NewTestGenesis( networkID uint32, xChainBalances XChainBalanceMap, - // cChainBalances core.GenesisAlloc, + cChainBalances core.GenesisAlloc, validatorIDs []ids.NodeID, ) (*genesis.UnparsedConfig, error) { // Validate inputs @@ -318,7 +322,7 @@ func NewTestGenesis( if len(validatorIDs) == 0 { return nil, errMissingValidatorsForGenesis } - if len(xChainBalances) == 0 /*|| len(cChainBalances) == 0*/ { + if len(xChainBalances) == 0 || len(cChainBalances) == 0 { return nil, errMissingBalancesForGenesis } @@ -390,20 +394,20 @@ func NewTestGenesis( ) } - // // Define C-Chain genesis - // cChainGenesis := &core.Genesis{ - // Config: ¶ms.ChainConfig{ - // ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary - // }, - // Difficulty: big.NewInt(0), // Difficulty is a mandatory field - // GasLimit: DefaultGasLimit, - // Alloc: cChainBalances, - // } - // cChainGenesisBytes, err := json.Marshal(cChainGenesis) - // if err != nil { - // return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) - // } - // config.CChainGenesis = string(cChainGenesisBytes) + // Define C-Chain genesis + cChainGenesis := &core.Genesis{ + Config: ¶ms.ChainConfig{ + ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary + }, + Difficulty: big.NewInt(0), // Difficulty is a mandatory field + GasLimit: DefaultGasLimit, + Alloc: cChainBalances, + } + cChainGenesisBytes, err := json.Marshal(cChainGenesis) + if err != nil { + return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) + } + config.CChainGenesis = string(cChainGenesisBytes) // Give staking rewards for initial validators to a random address. Any testing of staking rewards // will be easier to perform with nodes other than the initial validators since the timing of diff --git a/vms/example/xsvm/cmd/chain/create/cmd.go b/vms/example/xsvm/cmd/chain/create/cmd.go index 043b4298dcdf..1f00491a4ce6 100644 --- a/vms/example/xsvm/cmd/chain/create/cmd.go +++ b/vms/example/xsvm/cmd/chain/create/cmd.go @@ -42,9 +42,9 @@ func createFunc(c *cobra.Command, args []string) error { // that [uri] is hosting. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: config.URI, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: config.URI, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(config.SubnetID), }) if err != nil { diff --git a/wallet/chain/c/backend.go b/wallet/chain/c/backend.go index b88c8c643bc3..0a735116b646 100644 --- a/wallet/chain/c/backend.go +++ b/wallet/chain/c/backend.go @@ -3,153 +3,153 @@ package c -// import ( -// "errors" -// "fmt" -// "math/big" -// "sync" - -// stdcontext "context" - -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/database" -// "github.com/ava-labs/avalanchego/utils/math" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var ( -// _ Backend = (*backend)(nil) - -// errUnknownTxType = errors.New("unknown tx type") -// ) - -// // Backend defines the full interface required to support a C-chain wallet. -// type Backend interface { -// common.ChainUTXOs -// BuilderBackend -// SignerBackend - -// AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error -// } - -// type backend struct { -// Context -// common.ChainUTXOs - -// accountsLock sync.RWMutex -// accounts map[ethcommon.Address]*Account -// } - -// type Account struct { -// Balance *big.Int -// Nonce uint64 -// } - -// func NewBackend( -// ctx Context, -// utxos common.ChainUTXOs, -// accounts map[ethcommon.Address]*Account, -// ) Backend { -// return &backend{ -// Context: ctx, -// ChainUTXOs: utxos, -// accounts: accounts, -// } -// } - -// func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { -// switch tx := tx.UnsignedAtomicTx.(type) { -// case *evm.UnsignedImportTx: -// for _, input := range tx.ImportedInputs { -// utxoID := input.InputID() -// if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { -// return err -// } -// } - -// b.accountsLock.Lock() -// defer b.accountsLock.Unlock() - -// for _, output := range tx.Outs { -// account, ok := b.accounts[output.Address] -// if !ok { -// continue -// } - -// balance := new(big.Int).SetUint64(output.Amount) -// balance.Mul(balance, avaxConversionRate) -// account.Balance.Add(account.Balance, balance) -// } -// case *evm.UnsignedExportTx: -// txID := tx.ID() -// for i, out := range tx.ExportedOutputs { -// err := b.AddUTXO( -// ctx, -// tx.DestinationChain, -// &avax.UTXO{ -// UTXOID: avax.UTXOID{ -// TxID: txID, -// OutputIndex: uint32(i), -// }, -// Asset: avax.Asset{ID: out.AssetID()}, -// Out: out.Out, -// }, -// ) -// if err != nil { -// return err -// } -// } - -// b.accountsLock.Lock() -// defer b.accountsLock.Unlock() - -// for _, input := range tx.Ins { -// account, ok := b.accounts[input.Address] -// if !ok { -// continue -// } - -// balance := new(big.Int).SetUint64(input.Amount) -// balance.Mul(balance, avaxConversionRate) -// if account.Balance.Cmp(balance) == -1 { -// return errInsufficientFunds -// } -// account.Balance.Sub(account.Balance, balance) - -// newNonce, err := math.Add64(input.Nonce, 1) -// if err != nil { -// return err -// } -// account.Nonce = newNonce -// } -// default: -// return fmt.Errorf("%w: %T", errUnknownTxType, tx) -// } -// return nil -// } - -// func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { -// b.accountsLock.RLock() -// defer b.accountsLock.RUnlock() - -// account, exists := b.accounts[addr] -// if !exists { -// return nil, database.ErrNotFound -// } -// return account.Balance, nil -// } - -// func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { -// b.accountsLock.RLock() -// defer b.accountsLock.RUnlock() - -// account, exists := b.accounts[addr] -// if !exists { -// return 0, database.ErrNotFound -// } -// return account.Nonce, nil -// } +import ( + "errors" + "fmt" + "math/big" + "sync" + + stdcontext "context" + + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/utils/math" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var ( + _ Backend = (*backend)(nil) + + errUnknownTxType = errors.New("unknown tx type") +) + +// Backend defines the full interface required to support a C-chain wallet. +type Backend interface { + common.ChainUTXOs + BuilderBackend + SignerBackend + + AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error +} + +type backend struct { + Context + common.ChainUTXOs + + accountsLock sync.RWMutex + accounts map[ethcommon.Address]*Account +} + +type Account struct { + Balance *big.Int + Nonce uint64 +} + +func NewBackend( + ctx Context, + utxos common.ChainUTXOs, + accounts map[ethcommon.Address]*Account, +) Backend { + return &backend{ + Context: ctx, + ChainUTXOs: utxos, + accounts: accounts, + } +} + +func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { + switch tx := tx.UnsignedAtomicTx.(type) { + case *evm.UnsignedImportTx: + for _, input := range tx.ImportedInputs { + utxoID := input.InputID() + if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { + return err + } + } + + b.accountsLock.Lock() + defer b.accountsLock.Unlock() + + for _, output := range tx.Outs { + account, ok := b.accounts[output.Address] + if !ok { + continue + } + + balance := new(big.Int).SetUint64(output.Amount) + balance.Mul(balance, avaxConversionRate) + account.Balance.Add(account.Balance, balance) + } + case *evm.UnsignedExportTx: + txID := tx.ID() + for i, out := range tx.ExportedOutputs { + err := b.AddUTXO( + ctx, + tx.DestinationChain, + &avax.UTXO{ + UTXOID: avax.UTXOID{ + TxID: txID, + OutputIndex: uint32(i), + }, + Asset: avax.Asset{ID: out.AssetID()}, + Out: out.Out, + }, + ) + if err != nil { + return err + } + } + + b.accountsLock.Lock() + defer b.accountsLock.Unlock() + + for _, input := range tx.Ins { + account, ok := b.accounts[input.Address] + if !ok { + continue + } + + balance := new(big.Int).SetUint64(input.Amount) + balance.Mul(balance, avaxConversionRate) + if account.Balance.Cmp(balance) == -1 { + return errInsufficientFunds + } + account.Balance.Sub(account.Balance, balance) + + newNonce, err := math.Add64(input.Nonce, 1) + if err != nil { + return err + } + account.Nonce = newNonce + } + default: + return fmt.Errorf("%w: %T", errUnknownTxType, tx) + } + return nil +} + +func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { + b.accountsLock.RLock() + defer b.accountsLock.RUnlock() + + account, exists := b.accounts[addr] + if !exists { + return nil, database.ErrNotFound + } + return account.Balance, nil +} + +func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { + b.accountsLock.RLock() + defer b.accountsLock.RUnlock() + + account, exists := b.accounts[addr] + if !exists { + return 0, database.ErrNotFound + } + return account.Nonce, nil +} diff --git a/wallet/chain/c/builder.go b/wallet/chain/c/builder.go index c51d2647777e..d2d088e88a53 100644 --- a/wallet/chain/c/builder.go +++ b/wallet/chain/c/builder.go @@ -3,399 +3,399 @@ package c -// import ( -// "errors" -// "math/big" - -// stdcontext "context" - -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils" -// "github.com/ava-labs/avalanchego/utils/math" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// const avaxConversionRateInt = 1_000_000_000 - -// var ( -// _ Builder = (*builder)(nil) - -// errInsufficientFunds = errors.New("insufficient funds") - -// // avaxConversionRate is the conversion rate between the smallest -// // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest -// // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. -// // -// // This is only required for AVAX because the denomination of 1 AVAX is 9 -// // decimal places on the X and P chains, but is 18 decimal places within the -// // EVM. -// avaxConversionRate = big.NewInt(avaxConversionRateInt) -// ) - -// // Builder provides a convenient interface for building unsigned C-chain -// // transactions. -// type Builder interface { -// // GetBalance calculates the amount of AVAX that this builder has control -// // over. -// GetBalance( -// options ...common.Option, -// ) (*big.Int, error) - -// // GetImportableBalance calculates the amount of AVAX that this builder -// // could import from the provided chain. -// // -// // - [chainID] specifies the chain the funds are from. -// GetImportableBalance( -// chainID ids.ID, -// options ...common.Option, -// ) (uint64, error) - -// // NewImportTx creates an import transaction that attempts to consume all -// // the available UTXOs and import the funds to [to]. -// // -// // - [chainID] specifies the chain to be importing funds from. -// // - [to] specifies where to send the imported funds to. -// // - [baseFee] specifies the fee price willing to be paid by this tx. -// NewImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedImportTx, error) - -// // NewExportTx creates an export transaction that attempts to send all the -// // provided [outputs] to the requested [chainID]. -// // -// // - [chainID] specifies the chain to be exporting the funds to. -// // - [outputs] specifies the outputs to send to the [chainID]. -// // - [baseFee] specifies the fee price willing to be paid by this tx. -// NewExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedExportTx, error) -// } - -// // BuilderBackend specifies the required information needed to build unsigned -// // C-chain transactions. -// type BuilderBackend interface { -// Context - -// UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) -// Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) -// Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) -// } - -// type builder struct { -// avaxAddrs set.Set[ids.ShortID] -// ethAddrs set.Set[ethcommon.Address] -// backend BuilderBackend -// } - -// // NewBuilder returns a new transaction builder. -// // -// // - [avaxAddrs] is the set of addresses in the AVAX format that the builder -// // assumes can be used when signing the transactions in the future. -// // - [ethAddrs] is the set of addresses in the Eth format that the builder -// // assumes can be used when signing the transactions in the future. -// // - [backend] provides the required access to the chain's context and state -// // to build out the transactions. -// func NewBuilder( -// avaxAddrs set.Set[ids.ShortID], -// ethAddrs set.Set[ethcommon.Address], -// backend BuilderBackend, -// ) Builder { -// return &builder{ -// avaxAddrs: avaxAddrs, -// ethAddrs: ethAddrs, -// backend: backend, -// } -// } - -// func (b *builder) GetBalance( -// options ...common.Option, -// ) (*big.Int, error) { -// var ( -// ops = common.NewOptions(options) -// ctx = ops.Context() -// addrs = ops.EthAddresses(b.ethAddrs) -// totalBalance = new(big.Int) -// ) -// for addr := range addrs { -// balance, err := b.backend.Balance(ctx, addr) -// if err != nil { -// return nil, err -// } -// totalBalance.Add(totalBalance, balance) -// } - -// return totalBalance, nil -// } - -// func (b *builder) GetImportableBalance( -// chainID ids.ID, -// options ...common.Option, -// ) (uint64, error) { -// ops := common.NewOptions(options) -// utxos, err := b.backend.UTXOs(ops.Context(), chainID) -// if err != nil { -// return 0, err -// } - -// var ( -// addrs = ops.Addresses(b.avaxAddrs) -// minIssuanceTime = ops.MinIssuanceTime() -// avaxAssetID = b.backend.AVAXAssetID() -// balance uint64 -// ) -// for _, utxo := range utxos { -// amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) -// if !ok { -// continue -// } - -// newBalance, err := math.Add64(balance, amount) -// if err != nil { -// return 0, err -// } -// balance = newBalance -// } - -// return balance, nil -// } - -// func (b *builder) NewImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedImportTx, error) { -// ops := common.NewOptions(options) -// utxos, err := b.backend.UTXOs(ops.Context(), chainID) -// if err != nil { -// return nil, err -// } - -// var ( -// addrs = ops.Addresses(b.avaxAddrs) -// minIssuanceTime = ops.MinIssuanceTime() -// avaxAssetID = b.backend.AVAXAssetID() - -// importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) -// importedAmount uint64 -// ) -// for _, utxo := range utxos { -// amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) -// if !ok { -// continue -// } - -// importedInputs = append(importedInputs, &avax.TransferableInput{ -// UTXOID: utxo.UTXOID, -// Asset: utxo.Asset, -// In: &secp256k1fx.TransferInput{ -// Amt: amount, -// Input: secp256k1fx.Input{ -// SigIndices: inputSigIndices, -// }, -// }, -// }) - -// newImportedAmount, err := math.Add64(importedAmount, amount) -// if err != nil { -// return nil, err -// } -// importedAmount = newImportedAmount -// } - -// utils.Sort(importedInputs) -// tx := &evm.UnsignedImportTx{ -// NetworkID: b.backend.NetworkID(), -// BlockchainID: b.backend.BlockchainID(), -// SourceChain: chainID, -// ImportedInputs: importedInputs, -// } - -// // We must initialize the bytes of the tx to calculate the initial cost -// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} -// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { -// return nil, err -// } - -// gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) -// if err != nil { -// return nil, err -// } -// gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas - -// txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) -// if err != nil { -// return nil, err -// } - -// if importedAmount <= txFee { -// return nil, errInsufficientFunds -// } - -// tx.Outs = []evm.EVMOutput{{ -// Address: to, -// Amount: importedAmount - txFee, -// AssetID: avaxAssetID, -// }} -// return tx, nil -// } - -// func (b *builder) NewExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedExportTx, error) { -// var ( -// avaxAssetID = b.backend.AVAXAssetID() -// exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) -// exportedAmount uint64 -// ) -// for i, output := range outputs { -// exportedOutputs[i] = &avax.TransferableOutput{ -// Asset: avax.Asset{ID: avaxAssetID}, -// Out: output, -// } - -// newExportedAmount, err := math.Add64(exportedAmount, output.Amt) -// if err != nil { -// return nil, err -// } -// exportedAmount = newExportedAmount -// } - -// avax.SortTransferableOutputs(exportedOutputs, evm.Codec) -// tx := &evm.UnsignedExportTx{ -// NetworkID: b.backend.NetworkID(), -// BlockchainID: b.backend.BlockchainID(), -// DestinationChain: chainID, -// ExportedOutputs: exportedOutputs, -// } - -// // We must initialize the bytes of the tx to calculate the initial cost -// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} -// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { -// return nil, err -// } - -// cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) -// if err != nil { -// return nil, err -// } - -// initialFee, err := evm.CalculateDynamicFee(cost, baseFee) -// if err != nil { -// return nil, err -// } - -// amountToConsume, err := math.Add64(exportedAmount, initialFee) -// if err != nil { -// return nil, err -// } - -// var ( -// ops = common.NewOptions(options) -// ctx = ops.Context() -// addrs = ops.EthAddresses(b.ethAddrs) -// inputs = make([]evm.EVMInput, 0, addrs.Len()) -// ) -// for addr := range addrs { -// if amountToConsume == 0 { -// break -// } - -// prevFee, err := evm.CalculateDynamicFee(cost, baseFee) -// if err != nil { -// return nil, err -// } - -// newCost := cost + evm.EVMInputGas -// newFee, err := evm.CalculateDynamicFee(newCost, baseFee) -// if err != nil { -// return nil, err -// } - -// additionalFee := newFee - prevFee - -// balance, err := b.backend.Balance(ctx, addr) -// if err != nil { -// return nil, err -// } - -// // Since the asset is AVAX, we divide by the avaxConversionRate to -// // convert back to the correct denomination of AVAX that can be -// // exported. -// avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() - -// // If the balance for [addr] is insufficient to cover the additional -// // cost of adding an input to the transaction, skip adding the input -// // altogether. -// if avaxBalance <= additionalFee { -// continue -// } - -// // Update the cost for the next iteration -// cost = newCost - -// amountToConsume, err = math.Add64(amountToConsume, additionalFee) -// if err != nil { -// return nil, err -// } - -// nonce, err := b.backend.Nonce(ctx, addr) -// if err != nil { -// return nil, err -// } - -// inputAmount := math.Min(amountToConsume, avaxBalance) -// inputs = append(inputs, evm.EVMInput{ -// Address: addr, -// Amount: inputAmount, -// AssetID: avaxAssetID, -// Nonce: nonce, -// }) -// amountToConsume -= inputAmount -// } - -// if amountToConsume > 0 { -// return nil, errInsufficientFunds -// } - -// utils.Sort(inputs) -// tx.Ins = inputs -// return tx, nil -// } - -// func getSpendableAmount( -// utxo *avax.UTXO, -// addrs set.Set[ids.ShortID], -// minIssuanceTime uint64, -// avaxAssetID ids.ID, -// ) (uint64, []uint32, bool) { -// if utxo.Asset.ID != avaxAssetID { -// // Only AVAX can be imported -// return 0, nil, false -// } - -// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) -// if !ok { -// // Can't import an unknown transfer output type -// return 0, nil, false -// } - -// inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) -// return out.Amt, inputSigIndices, ok -// } +import ( + "errors" + "math/big" + + stdcontext "context" + + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils" + "github.com/ava-labs/avalanchego/utils/math" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +const avaxConversionRateInt = 1_000_000_000 + +var ( + _ Builder = (*builder)(nil) + + errInsufficientFunds = errors.New("insufficient funds") + + // avaxConversionRate is the conversion rate between the smallest + // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest + // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. + // + // This is only required for AVAX because the denomination of 1 AVAX is 9 + // decimal places on the X and P chains, but is 18 decimal places within the + // EVM. + avaxConversionRate = big.NewInt(avaxConversionRateInt) +) + +// Builder provides a convenient interface for building unsigned C-chain +// transactions. +type Builder interface { + // GetBalance calculates the amount of AVAX that this builder has control + // over. + GetBalance( + options ...common.Option, + ) (*big.Int, error) + + // GetImportableBalance calculates the amount of AVAX that this builder + // could import from the provided chain. + // + // - [chainID] specifies the chain the funds are from. + GetImportableBalance( + chainID ids.ID, + options ...common.Option, + ) (uint64, error) + + // NewImportTx creates an import transaction that attempts to consume all + // the available UTXOs and import the funds to [to]. + // + // - [chainID] specifies the chain to be importing funds from. + // - [to] specifies where to send the imported funds to. + // - [baseFee] specifies the fee price willing to be paid by this tx. + NewImportTx( + chainID ids.ID, + to ethcommon.Address, + baseFee *big.Int, + options ...common.Option, + ) (*evm.UnsignedImportTx, error) + + // NewExportTx creates an export transaction that attempts to send all the + // provided [outputs] to the requested [chainID]. + // + // - [chainID] specifies the chain to be exporting the funds to. + // - [outputs] specifies the outputs to send to the [chainID]. + // - [baseFee] specifies the fee price willing to be paid by this tx. + NewExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + baseFee *big.Int, + options ...common.Option, + ) (*evm.UnsignedExportTx, error) +} + +// BuilderBackend specifies the required information needed to build unsigned +// C-chain transactions. +type BuilderBackend interface { + Context + + UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) + Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) + Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) +} + +type builder struct { + avaxAddrs set.Set[ids.ShortID] + ethAddrs set.Set[ethcommon.Address] + backend BuilderBackend +} + +// NewBuilder returns a new transaction builder. +// +// - [avaxAddrs] is the set of addresses in the AVAX format that the builder +// assumes can be used when signing the transactions in the future. +// - [ethAddrs] is the set of addresses in the Eth format that the builder +// assumes can be used when signing the transactions in the future. +// - [backend] provides the required access to the chain's context and state +// to build out the transactions. +func NewBuilder( + avaxAddrs set.Set[ids.ShortID], + ethAddrs set.Set[ethcommon.Address], + backend BuilderBackend, +) Builder { + return &builder{ + avaxAddrs: avaxAddrs, + ethAddrs: ethAddrs, + backend: backend, + } +} + +func (b *builder) GetBalance( + options ...common.Option, +) (*big.Int, error) { + var ( + ops = common.NewOptions(options) + ctx = ops.Context() + addrs = ops.EthAddresses(b.ethAddrs) + totalBalance = new(big.Int) + ) + for addr := range addrs { + balance, err := b.backend.Balance(ctx, addr) + if err != nil { + return nil, err + } + totalBalance.Add(totalBalance, balance) + } + + return totalBalance, nil +} + +func (b *builder) GetImportableBalance( + chainID ids.ID, + options ...common.Option, +) (uint64, error) { + ops := common.NewOptions(options) + utxos, err := b.backend.UTXOs(ops.Context(), chainID) + if err != nil { + return 0, err + } + + var ( + addrs = ops.Addresses(b.avaxAddrs) + minIssuanceTime = ops.MinIssuanceTime() + avaxAssetID = b.backend.AVAXAssetID() + balance uint64 + ) + for _, utxo := range utxos { + amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) + if !ok { + continue + } + + newBalance, err := math.Add64(balance, amount) + if err != nil { + return 0, err + } + balance = newBalance + } + + return balance, nil +} + +func (b *builder) NewImportTx( + chainID ids.ID, + to ethcommon.Address, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedImportTx, error) { + ops := common.NewOptions(options) + utxos, err := b.backend.UTXOs(ops.Context(), chainID) + if err != nil { + return nil, err + } + + var ( + addrs = ops.Addresses(b.avaxAddrs) + minIssuanceTime = ops.MinIssuanceTime() + avaxAssetID = b.backend.AVAXAssetID() + + importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) + importedAmount uint64 + ) + for _, utxo := range utxos { + amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) + if !ok { + continue + } + + importedInputs = append(importedInputs, &avax.TransferableInput{ + UTXOID: utxo.UTXOID, + Asset: utxo.Asset, + In: &secp256k1fx.TransferInput{ + Amt: amount, + Input: secp256k1fx.Input{ + SigIndices: inputSigIndices, + }, + }, + }) + + newImportedAmount, err := math.Add64(importedAmount, amount) + if err != nil { + return nil, err + } + importedAmount = newImportedAmount + } + + utils.Sort(importedInputs) + tx := &evm.UnsignedImportTx{ + NetworkID: b.backend.NetworkID(), + BlockchainID: b.backend.BlockchainID(), + SourceChain: chainID, + ImportedInputs: importedInputs, + } + + // We must initialize the bytes of the tx to calculate the initial cost + wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} + if err := wrappedTx.Sign(evm.Codec, nil); err != nil { + return nil, err + } + + gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) + if err != nil { + return nil, err + } + gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas + + txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) + if err != nil { + return nil, err + } + + if importedAmount <= txFee { + return nil, errInsufficientFunds + } + + tx.Outs = []evm.EVMOutput{{ + Address: to, + Amount: importedAmount - txFee, + AssetID: avaxAssetID, + }} + return tx, nil +} + +func (b *builder) NewExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedExportTx, error) { + var ( + avaxAssetID = b.backend.AVAXAssetID() + exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) + exportedAmount uint64 + ) + for i, output := range outputs { + exportedOutputs[i] = &avax.TransferableOutput{ + Asset: avax.Asset{ID: avaxAssetID}, + Out: output, + } + + newExportedAmount, err := math.Add64(exportedAmount, output.Amt) + if err != nil { + return nil, err + } + exportedAmount = newExportedAmount + } + + avax.SortTransferableOutputs(exportedOutputs, evm.Codec) + tx := &evm.UnsignedExportTx{ + NetworkID: b.backend.NetworkID(), + BlockchainID: b.backend.BlockchainID(), + DestinationChain: chainID, + ExportedOutputs: exportedOutputs, + } + + // We must initialize the bytes of the tx to calculate the initial cost + wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} + if err := wrappedTx.Sign(evm.Codec, nil); err != nil { + return nil, err + } + + cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) + if err != nil { + return nil, err + } + + initialFee, err := evm.CalculateDynamicFee(cost, baseFee) + if err != nil { + return nil, err + } + + amountToConsume, err := math.Add64(exportedAmount, initialFee) + if err != nil { + return nil, err + } + + var ( + ops = common.NewOptions(options) + ctx = ops.Context() + addrs = ops.EthAddresses(b.ethAddrs) + inputs = make([]evm.EVMInput, 0, addrs.Len()) + ) + for addr := range addrs { + if amountToConsume == 0 { + break + } + + prevFee, err := evm.CalculateDynamicFee(cost, baseFee) + if err != nil { + return nil, err + } + + newCost := cost + evm.EVMInputGas + newFee, err := evm.CalculateDynamicFee(newCost, baseFee) + if err != nil { + return nil, err + } + + additionalFee := newFee - prevFee + + balance, err := b.backend.Balance(ctx, addr) + if err != nil { + return nil, err + } + + // Since the asset is AVAX, we divide by the avaxConversionRate to + // convert back to the correct denomination of AVAX that can be + // exported. + avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() + + // If the balance for [addr] is insufficient to cover the additional + // cost of adding an input to the transaction, skip adding the input + // altogether. + if avaxBalance <= additionalFee { + continue + } + + // Update the cost for the next iteration + cost = newCost + + amountToConsume, err = math.Add64(amountToConsume, additionalFee) + if err != nil { + return nil, err + } + + nonce, err := b.backend.Nonce(ctx, addr) + if err != nil { + return nil, err + } + + inputAmount := math.Min(amountToConsume, avaxBalance) + inputs = append(inputs, evm.EVMInput{ + Address: addr, + Amount: inputAmount, + AssetID: avaxAssetID, + Nonce: nonce, + }) + amountToConsume -= inputAmount + } + + if amountToConsume > 0 { + return nil, errInsufficientFunds + } + + utils.Sort(inputs) + tx.Ins = inputs + return tx, nil +} + +func getSpendableAmount( + utxo *avax.UTXO, + addrs set.Set[ids.ShortID], + minIssuanceTime uint64, + avaxAssetID ids.ID, +) (uint64, []uint32, bool) { + if utxo.Asset.ID != avaxAssetID { + // Only AVAX can be imported + return 0, nil, false + } + + out, ok := utxo.Out.(*secp256k1fx.TransferOutput) + if !ok { + // Can't import an unknown transfer output type + return 0, nil, false + } + + inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) + return out.Amt, inputSigIndices, ok +} diff --git a/wallet/chain/c/builder_with_options.go b/wallet/chain/c/builder_with_options.go index 9b7ab8399484..8416dddf9928 100644 --- a/wallet/chain/c/builder_with_options.go +++ b/wallet/chain/c/builder_with_options.go @@ -3,81 +3,81 @@ package c -// import ( -// "math/big" +import ( + "math/big" -// "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/coreth/plugin/evm" -// ethcommon "github.com/ethereum/go-ethereum/common" + ethcommon "github.com/ethereum/go-ethereum/common" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) -// var _ Builder = (*builderWithOptions)(nil) +var _ Builder = (*builderWithOptions)(nil) -// type builderWithOptions struct { -// Builder -// options []common.Option -// } +type builderWithOptions struct { + Builder + options []common.Option +} -// // NewBuilderWithOptions returns a new transaction builder that will use the -// // given options by default. -// // -// // - [builder] is the builder that will be called to perform the underlying -// // operations. -// // - [options] will be provided to the builder in addition to the options -// // provided in the method calls. -// func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { -// return &builderWithOptions{ -// Builder: builder, -// options: options, -// } -// } +// NewBuilderWithOptions returns a new transaction builder that will use the +// given options by default. +// +// - [builder] is the builder that will be called to perform the underlying +// operations. +// - [options] will be provided to the builder in addition to the options +// provided in the method calls. +func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { + return &builderWithOptions{ + Builder: builder, + options: options, + } +} -// func (b *builderWithOptions) GetBalance( -// options ...common.Option, -// ) (*big.Int, error) { -// return b.Builder.GetBalance( -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) GetBalance( + options ...common.Option, +) (*big.Int, error) { + return b.Builder.GetBalance( + common.UnionOptions(b.options, options)..., + ) +} -// func (b *builderWithOptions) GetImportableBalance( -// chainID ids.ID, -// options ...common.Option, -// ) (uint64, error) { -// return b.Builder.GetImportableBalance( -// chainID, -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) GetImportableBalance( + chainID ids.ID, + options ...common.Option, +) (uint64, error) { + return b.Builder.GetImportableBalance( + chainID, + common.UnionOptions(b.options, options)..., + ) +} -// func (b *builderWithOptions) NewImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedImportTx, error) { -// return b.Builder.NewImportTx( -// chainID, -// to, -// baseFee, -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) NewImportTx( + chainID ids.ID, + to ethcommon.Address, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedImportTx, error) { + return b.Builder.NewImportTx( + chainID, + to, + baseFee, + common.UnionOptions(b.options, options)..., + ) +} -// func (b *builderWithOptions) NewExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedExportTx, error) { -// return b.Builder.NewExportTx( -// chainID, -// outputs, -// baseFee, -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) NewExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedExportTx, error) { + return b.Builder.NewExportTx( + chainID, + outputs, + baseFee, + common.UnionOptions(b.options, options)..., + ) +} diff --git a/wallet/chain/c/context.go b/wallet/chain/c/context.go index 1c01d8fb55c8..d506b42f81fa 100644 --- a/wallet/chain/c/context.go +++ b/wallet/chain/c/context.go @@ -3,81 +3,81 @@ package c -// import ( -// stdcontext "context" +import ( + stdcontext "context" -// "github.com/ava-labs/avalanchego/api/info" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/avm" -// ) + "github.com/ava-labs/avalanchego/api/info" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/avm" +) -// var _ Context = (*context)(nil) +var _ Context = (*context)(nil) -// type Context interface { -// NetworkID() uint32 -// BlockchainID() ids.ID -// AVAXAssetID() ids.ID -// } +type Context interface { + NetworkID() uint32 + BlockchainID() ids.ID + AVAXAssetID() ids.ID +} -// type context struct { -// networkID uint32 -// blockchainID ids.ID -// avaxAssetID ids.ID -// } +type context struct { + networkID uint32 + blockchainID ids.ID + avaxAssetID ids.ID +} -// func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { -// infoClient := info.NewClient(uri) -// xChainClient := avm.NewClient(uri, "X") -// return NewContextFromClients(ctx, infoClient, xChainClient) -// } +func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { + infoClient := info.NewClient(uri) + xChainClient := avm.NewClient(uri, "X") + return NewContextFromClients(ctx, infoClient, xChainClient) +} -// func NewContextFromClients( -// ctx stdcontext.Context, -// infoClient info.Client, -// xChainClient avm.Client, -// ) (Context, error) { -// networkID, err := infoClient.GetNetworkID(ctx) -// if err != nil { -// return nil, err -// } +func NewContextFromClients( + ctx stdcontext.Context, + infoClient info.Client, + xChainClient avm.Client, +) (Context, error) { + networkID, err := infoClient.GetNetworkID(ctx) + if err != nil { + return nil, err + } -// chainID, err := infoClient.GetBlockchainID(ctx, "C") -// if err != nil { -// return nil, err -// } + chainID, err := infoClient.GetBlockchainID(ctx, "C") + if err != nil { + return nil, err + } -// asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") -// if err != nil { -// return nil, err -// } + asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") + if err != nil { + return nil, err + } -// return NewContext( -// networkID, -// chainID, -// asset.AssetID, -// ), nil -// } + return NewContext( + networkID, + chainID, + asset.AssetID, + ), nil +} -// func NewContext( -// networkID uint32, -// blockchainID ids.ID, -// avaxAssetID ids.ID, -// ) Context { -// return &context{ -// networkID: networkID, -// blockchainID: blockchainID, -// avaxAssetID: avaxAssetID, -// } -// } +func NewContext( + networkID uint32, + blockchainID ids.ID, + avaxAssetID ids.ID, +) Context { + return &context{ + networkID: networkID, + blockchainID: blockchainID, + avaxAssetID: avaxAssetID, + } +} -// func (c *context) NetworkID() uint32 { -// return c.networkID -// } +func (c *context) NetworkID() uint32 { + return c.networkID +} -// func (c *context) BlockchainID() ids.ID { -// return c.blockchainID -// } +func (c *context) BlockchainID() ids.ID { + return c.blockchainID +} -// func (c *context) AVAXAssetID() ids.ID { -// return c.avaxAssetID -// } +func (c *context) AVAXAssetID() ids.ID { + return c.avaxAssetID +} diff --git a/wallet/chain/c/signer.go b/wallet/chain/c/signer.go index 4bedc378234b..4fd85ed3b532 100644 --- a/wallet/chain/c/signer.go +++ b/wallet/chain/c/signer.go @@ -3,221 +3,221 @@ package c -// import ( -// "errors" -// "fmt" - -// stdcontext "context" - -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/database" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils/crypto/keychain" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/hashing" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/components/verify" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// ) - -// const version = 0 - -// var ( -// _ Signer = (*txSigner)(nil) - -// errUnknownInputType = errors.New("unknown input type") -// errUnknownCredentialType = errors.New("unknown credential type") -// errUnknownOutputType = errors.New("unknown output type") -// errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") - -// emptySig [secp256k1.SignatureLen]byte -// ) - -// type Signer interface { -// SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) -// SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error -// } - -// type EthKeychain interface { -// // The returned Signer can provide a signature for [addr] -// GetEth(addr ethcommon.Address) (keychain.Signer, bool) -// // Returns the set of addresses for which the accessor keeps an associated -// // signer -// EthAddresses() set.Set[ethcommon.Address] -// } - -// type SignerBackend interface { -// GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) -// } - -// type txSigner struct { -// avaxKC keychain.Keychain -// ethKC EthKeychain -// backend SignerBackend -// } - -// func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { -// return &txSigner{ -// avaxKC: avaxKC, -// ethKC: ethKC, -// backend: backend, -// } -// } - -// func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { -// tx := &evm.Tx{UnsignedAtomicTx: utx} -// return tx, s.SignAtomic(ctx, tx) -// } - -// func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { -// switch utx := tx.UnsignedAtomicTx.(type) { -// case *evm.UnsignedImportTx: -// signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) -// if err != nil { -// return err -// } -// return sign(tx, true, signers) -// case *evm.UnsignedExportTx: -// signers := s.getExportSigners(utx.Ins) -// return sign(tx, true, signers) -// default: -// return fmt.Errorf("%w: %T", errUnknownTxType, tx) -// } -// } - -// func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { -// txSigners := make([][]keychain.Signer, len(ins)) -// for credIndex, transferInput := range ins { -// input, ok := transferInput.In.(*secp256k1fx.TransferInput) -// if !ok { -// return nil, errUnknownInputType -// } - -// inputSigners := make([]keychain.Signer, len(input.SigIndices)) -// txSigners[credIndex] = inputSigners - -// utxoID := transferInput.InputID() -// utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) -// if err == database.ErrNotFound { -// // If we don't have access to the UTXO, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// if err != nil { -// return nil, err -// } - -// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) -// if !ok { -// return nil, errUnknownOutputType -// } - -// for sigIndex, addrIndex := range input.SigIndices { -// if addrIndex >= uint32(len(out.Addrs)) { -// return nil, errInvalidUTXOSigIndex -// } - -// addr := out.Addrs[addrIndex] -// key, ok := s.avaxKC.Get(addr) -// if !ok { -// // If we don't have access to the key, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// inputSigners[sigIndex] = key -// } -// } -// return txSigners, nil -// } - -// func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { -// txSigners := make([][]keychain.Signer, len(ins)) -// for credIndex, input := range ins { -// inputSigners := make([]keychain.Signer, 1) -// txSigners[credIndex] = inputSigners - -// key, ok := s.ethKC.GetEth(input.Address) -// if !ok { -// // If we don't have access to the key, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// inputSigners[0] = key -// } -// return txSigners -// } - -// // TODO: remove [signHash] after the ledger supports signing all transactions. -// func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { -// unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) -// if err != nil { -// return fmt.Errorf("couldn't marshal unsigned tx: %w", err) -// } -// unsignedHash := hashing.ComputeHash256(unsignedBytes) - -// if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { -// tx.Creds = make([]verify.Verifiable, expectedLen) -// } - -// sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) -// for credIndex, inputSigners := range txSigners { -// credIntf := tx.Creds[credIndex] -// if credIntf == nil { -// credIntf = &secp256k1fx.Credential{} -// tx.Creds[credIndex] = credIntf -// } - -// cred, ok := credIntf.(*secp256k1fx.Credential) -// if !ok { -// return errUnknownCredentialType -// } -// if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { -// cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) -// } - -// for sigIndex, signer := range inputSigners { -// if signer == nil { -// // If we don't have access to the key, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// addr := signer.Address() -// if sig := cred.Sigs[sigIndex]; sig != emptySig { -// // If this signature has already been populated, we can just -// // copy the needed signature for the future. -// sigCache[addr] = sig -// continue -// } - -// if sig, exists := sigCache[addr]; exists { -// // If this key has already produced a signature, we can just -// // copy the previous signature. -// cred.Sigs[sigIndex] = sig -// continue -// } - -// var sig []byte -// if signHash { -// sig, err = signer.SignHash(unsignedHash) -// } else { -// sig, err = signer.Sign(unsignedBytes) -// } -// if err != nil { -// return fmt.Errorf("problem signing tx: %w", err) -// } -// copy(cred.Sigs[sigIndex][:], sig) -// sigCache[addr] = cred.Sigs[sigIndex] -// } -// } - -// signedBytes, err := evm.Codec.Marshal(version, tx) -// if err != nil { -// return fmt.Errorf("couldn't marshal tx: %w", err) -// } -// tx.Initialize(unsignedBytes, signedBytes) -// return nil -// } +import ( + "errors" + "fmt" + + stdcontext "context" + + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/crypto/keychain" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/hashing" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/components/verify" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" +) + +const version = 0 + +var ( + _ Signer = (*txSigner)(nil) + + errUnknownInputType = errors.New("unknown input type") + errUnknownCredentialType = errors.New("unknown credential type") + errUnknownOutputType = errors.New("unknown output type") + errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") + + emptySig [secp256k1.SignatureLen]byte +) + +type Signer interface { + SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) + SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error +} + +type EthKeychain interface { + // The returned Signer can provide a signature for [addr] + GetEth(addr ethcommon.Address) (keychain.Signer, bool) + // Returns the set of addresses for which the accessor keeps an associated + // signer + EthAddresses() set.Set[ethcommon.Address] +} + +type SignerBackend interface { + GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) +} + +type txSigner struct { + avaxKC keychain.Keychain + ethKC EthKeychain + backend SignerBackend +} + +func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { + return &txSigner{ + avaxKC: avaxKC, + ethKC: ethKC, + backend: backend, + } +} + +func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { + tx := &evm.Tx{UnsignedAtomicTx: utx} + return tx, s.SignAtomic(ctx, tx) +} + +func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { + switch utx := tx.UnsignedAtomicTx.(type) { + case *evm.UnsignedImportTx: + signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) + if err != nil { + return err + } + return sign(tx, true, signers) + case *evm.UnsignedExportTx: + signers := s.getExportSigners(utx.Ins) + return sign(tx, true, signers) + default: + return fmt.Errorf("%w: %T", errUnknownTxType, tx) + } +} + +func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { + txSigners := make([][]keychain.Signer, len(ins)) + for credIndex, transferInput := range ins { + input, ok := transferInput.In.(*secp256k1fx.TransferInput) + if !ok { + return nil, errUnknownInputType + } + + inputSigners := make([]keychain.Signer, len(input.SigIndices)) + txSigners[credIndex] = inputSigners + + utxoID := transferInput.InputID() + utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) + if err == database.ErrNotFound { + // If we don't have access to the UTXO, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + if err != nil { + return nil, err + } + + out, ok := utxo.Out.(*secp256k1fx.TransferOutput) + if !ok { + return nil, errUnknownOutputType + } + + for sigIndex, addrIndex := range input.SigIndices { + if addrIndex >= uint32(len(out.Addrs)) { + return nil, errInvalidUTXOSigIndex + } + + addr := out.Addrs[addrIndex] + key, ok := s.avaxKC.Get(addr) + if !ok { + // If we don't have access to the key, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + inputSigners[sigIndex] = key + } + } + return txSigners, nil +} + +func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { + txSigners := make([][]keychain.Signer, len(ins)) + for credIndex, input := range ins { + inputSigners := make([]keychain.Signer, 1) + txSigners[credIndex] = inputSigners + + key, ok := s.ethKC.GetEth(input.Address) + if !ok { + // If we don't have access to the key, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + inputSigners[0] = key + } + return txSigners +} + +// TODO: remove [signHash] after the ledger supports signing all transactions. +func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { + unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) + if err != nil { + return fmt.Errorf("couldn't marshal unsigned tx: %w", err) + } + unsignedHash := hashing.ComputeHash256(unsignedBytes) + + if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { + tx.Creds = make([]verify.Verifiable, expectedLen) + } + + sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) + for credIndex, inputSigners := range txSigners { + credIntf := tx.Creds[credIndex] + if credIntf == nil { + credIntf = &secp256k1fx.Credential{} + tx.Creds[credIndex] = credIntf + } + + cred, ok := credIntf.(*secp256k1fx.Credential) + if !ok { + return errUnknownCredentialType + } + if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { + cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) + } + + for sigIndex, signer := range inputSigners { + if signer == nil { + // If we don't have access to the key, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + addr := signer.Address() + if sig := cred.Sigs[sigIndex]; sig != emptySig { + // If this signature has already been populated, we can just + // copy the needed signature for the future. + sigCache[addr] = sig + continue + } + + if sig, exists := sigCache[addr]; exists { + // If this key has already produced a signature, we can just + // copy the previous signature. + cred.Sigs[sigIndex] = sig + continue + } + + var sig []byte + if signHash { + sig, err = signer.SignHash(unsignedHash) + } else { + sig, err = signer.Sign(unsignedBytes) + } + if err != nil { + return fmt.Errorf("problem signing tx: %w", err) + } + copy(cred.Sigs[sigIndex][:], sig) + sigCache[addr] = cred.Sigs[sigIndex] + } + } + + signedBytes, err := evm.Codec.Marshal(version, tx) + if err != nil { + return fmt.Errorf("couldn't marshal tx: %w", err) + } + tx.Initialize(unsignedBytes, signedBytes) + return nil +} diff --git a/wallet/chain/c/wallet.go b/wallet/chain/c/wallet.go index ebee50a9a958..fb1a83d53dad 100644 --- a/wallet/chain/c/wallet.go +++ b/wallet/chain/c/wallet.go @@ -3,204 +3,204 @@ package c -// import ( -// "errors" -// "math/big" -// "time" - -// "github.com/ava-labs/coreth/ethclient" -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var ( -// _ Wallet = (*wallet)(nil) - -// errNotCommitted = errors.New("not committed") -// ) - -// type Wallet interface { -// Context - -// // Builder returns the builder that will be used to create the transactions. -// Builder() Builder - -// // Signer returns the signer that will be used to sign the transactions. -// Signer() Signer - -// // IssueImportTx creates, signs, and issues an import transaction that -// // attempts to consume all the available UTXOs and import the funds to [to]. -// // -// // - [chainID] specifies the chain to be importing funds from. -// // - [to] specifies where to send the imported funds to. -// IssueImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// options ...common.Option, -// ) (*evm.Tx, error) - -// // IssueExportTx creates, signs, and issues an export transaction that -// // attempts to send all the provided [outputs] to the requested [chainID]. -// // -// // - [chainID] specifies the chain to be exporting the funds to. -// // - [outputs] specifies the outputs to send to the [chainID]. -// IssueExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// options ...common.Option, -// ) (*evm.Tx, error) - -// // IssueUnsignedTx signs and issues the unsigned tx. -// IssueUnsignedAtomicTx( -// utx evm.UnsignedAtomicTx, -// options ...common.Option, -// ) (*evm.Tx, error) - -// // IssueAtomicTx issues the signed tx. -// IssueAtomicTx( -// tx *evm.Tx, -// options ...common.Option, -// ) error -// } - -// func NewWallet( -// builder Builder, -// signer Signer, -// avaxClient evm.Client, -// ethClient ethclient.Client, -// backend Backend, -// ) Wallet { -// return &wallet{ -// Backend: backend, -// builder: builder, -// signer: signer, -// avaxClient: avaxClient, -// ethClient: ethClient, -// } -// } - -// type wallet struct { -// Backend -// builder Builder -// signer Signer -// avaxClient evm.Client -// ethClient ethclient.Client -// } - -// func (w *wallet) Builder() Builder { -// return w.builder -// } - -// func (w *wallet) Signer() Signer { -// return w.signer -// } - -// func (w *wallet) IssueImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// options ...common.Option, -// ) (*evm.Tx, error) { -// baseFee, err := w.baseFee(options) -// if err != nil { -// return nil, err -// } - -// utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) -// if err != nil { -// return nil, err -// } -// return w.IssueUnsignedAtomicTx(utx, options...) -// } - -// func (w *wallet) IssueExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// options ...common.Option, -// ) (*evm.Tx, error) { -// baseFee, err := w.baseFee(options) -// if err != nil { -// return nil, err -// } - -// utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) -// if err != nil { -// return nil, err -// } -// return w.IssueUnsignedAtomicTx(utx, options...) -// } - -// func (w *wallet) IssueUnsignedAtomicTx( -// utx evm.UnsignedAtomicTx, -// options ...common.Option, -// ) (*evm.Tx, error) { -// ops := common.NewOptions(options) -// ctx := ops.Context() -// tx, err := w.signer.SignUnsignedAtomic(ctx, utx) -// if err != nil { -// return nil, err -// } - -// return tx, w.IssueAtomicTx(tx, options...) -// } - -// func (w *wallet) IssueAtomicTx( -// tx *evm.Tx, -// options ...common.Option, -// ) error { -// ops := common.NewOptions(options) -// ctx := ops.Context() -// txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) -// if err != nil { -// return err -// } - -// if f := ops.PostIssuanceFunc(); f != nil { -// f(txID) -// } - -// if ops.AssumeDecided() { -// return w.Backend.AcceptAtomicTx(ctx, tx) -// } - -// pollFrequency := ops.PollFrequency() -// ticker := time.NewTicker(pollFrequency) -// defer ticker.Stop() - -// for { -// status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) -// if err != nil { -// return err -// } - -// switch status { -// case evm.Accepted: -// return w.Backend.AcceptAtomicTx(ctx, tx) -// case evm.Dropped, evm.Unknown: -// return errNotCommitted -// } - -// // The tx is Processing. - -// select { -// case <-ticker.C: -// case <-ctx.Done(): -// return ctx.Err() -// } -// } -// } - -// func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { -// ops := common.NewOptions(options) -// baseFee := ops.BaseFee(nil) -// if baseFee != nil { -// return baseFee, nil -// } - -// ctx := ops.Context() -// return w.ethClient.EstimateBaseFee(ctx) -// } +import ( + "errors" + "math/big" + "time" + + "github.com/ava-labs/coreth/ethclient" + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var ( + _ Wallet = (*wallet)(nil) + + errNotCommitted = errors.New("not committed") +) + +type Wallet interface { + Context + + // Builder returns the builder that will be used to create the transactions. + Builder() Builder + + // Signer returns the signer that will be used to sign the transactions. + Signer() Signer + + // IssueImportTx creates, signs, and issues an import transaction that + // attempts to consume all the available UTXOs and import the funds to [to]. + // + // - [chainID] specifies the chain to be importing funds from. + // - [to] specifies where to send the imported funds to. + IssueImportTx( + chainID ids.ID, + to ethcommon.Address, + options ...common.Option, + ) (*evm.Tx, error) + + // IssueExportTx creates, signs, and issues an export transaction that + // attempts to send all the provided [outputs] to the requested [chainID]. + // + // - [chainID] specifies the chain to be exporting the funds to. + // - [outputs] specifies the outputs to send to the [chainID]. + IssueExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + options ...common.Option, + ) (*evm.Tx, error) + + // IssueUnsignedTx signs and issues the unsigned tx. + IssueUnsignedAtomicTx( + utx evm.UnsignedAtomicTx, + options ...common.Option, + ) (*evm.Tx, error) + + // IssueAtomicTx issues the signed tx. + IssueAtomicTx( + tx *evm.Tx, + options ...common.Option, + ) error +} + +func NewWallet( + builder Builder, + signer Signer, + avaxClient evm.Client, + ethClient ethclient.Client, + backend Backend, +) Wallet { + return &wallet{ + Backend: backend, + builder: builder, + signer: signer, + avaxClient: avaxClient, + ethClient: ethClient, + } +} + +type wallet struct { + Backend + builder Builder + signer Signer + avaxClient evm.Client + ethClient ethclient.Client +} + +func (w *wallet) Builder() Builder { + return w.builder +} + +func (w *wallet) Signer() Signer { + return w.signer +} + +func (w *wallet) IssueImportTx( + chainID ids.ID, + to ethcommon.Address, + options ...common.Option, +) (*evm.Tx, error) { + baseFee, err := w.baseFee(options) + if err != nil { + return nil, err + } + + utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) + if err != nil { + return nil, err + } + return w.IssueUnsignedAtomicTx(utx, options...) +} + +func (w *wallet) IssueExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + options ...common.Option, +) (*evm.Tx, error) { + baseFee, err := w.baseFee(options) + if err != nil { + return nil, err + } + + utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) + if err != nil { + return nil, err + } + return w.IssueUnsignedAtomicTx(utx, options...) +} + +func (w *wallet) IssueUnsignedAtomicTx( + utx evm.UnsignedAtomicTx, + options ...common.Option, +) (*evm.Tx, error) { + ops := common.NewOptions(options) + ctx := ops.Context() + tx, err := w.signer.SignUnsignedAtomic(ctx, utx) + if err != nil { + return nil, err + } + + return tx, w.IssueAtomicTx(tx, options...) +} + +func (w *wallet) IssueAtomicTx( + tx *evm.Tx, + options ...common.Option, +) error { + ops := common.NewOptions(options) + ctx := ops.Context() + txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) + if err != nil { + return err + } + + if f := ops.PostIssuanceFunc(); f != nil { + f(txID) + } + + if ops.AssumeDecided() { + return w.Backend.AcceptAtomicTx(ctx, tx) + } + + pollFrequency := ops.PollFrequency() + ticker := time.NewTicker(pollFrequency) + defer ticker.Stop() + + for { + status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) + if err != nil { + return err + } + + switch status { + case evm.Accepted: + return w.Backend.AcceptAtomicTx(ctx, tx) + case evm.Dropped, evm.Unknown: + return errNotCommitted + } + + // The tx is Processing. + + select { + case <-ticker.C: + case <-ctx.Done(): + return ctx.Err() + } + } +} + +func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { + ops := common.NewOptions(options) + baseFee := ops.BaseFee(nil) + if baseFee != nil { + return baseFee, nil + } + + ctx := ops.Context() + return w.ethClient.EstimateBaseFee(ctx) +} diff --git a/wallet/chain/c/wallet_with_options.go b/wallet/chain/c/wallet_with_options.go index fd69a6d4fd02..7d6193683d49 100644 --- a/wallet/chain/c/wallet_with_options.go +++ b/wallet/chain/c/wallet_with_options.go @@ -3,80 +3,80 @@ package c -// import ( -// "github.com/ava-labs/coreth/plugin/evm" +import ( + "github.com/ava-labs/coreth/plugin/evm" -// ethcommon "github.com/ethereum/go-ethereum/common" + ethcommon "github.com/ethereum/go-ethereum/common" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) -// var _ Wallet = (*walletWithOptions)(nil) +var _ Wallet = (*walletWithOptions)(nil) -// func NewWalletWithOptions( -// wallet Wallet, -// options ...common.Option, -// ) Wallet { -// return &walletWithOptions{ -// Wallet: wallet, -// options: options, -// } -// } +func NewWalletWithOptions( + wallet Wallet, + options ...common.Option, +) Wallet { + return &walletWithOptions{ + Wallet: wallet, + options: options, + } +} -// type walletWithOptions struct { -// Wallet -// options []common.Option -// } +type walletWithOptions struct { + Wallet + options []common.Option +} -// func (w *walletWithOptions) Builder() Builder { -// return NewBuilderWithOptions( -// w.Wallet.Builder(), -// w.options..., -// ) -// } +func (w *walletWithOptions) Builder() Builder { + return NewBuilderWithOptions( + w.Wallet.Builder(), + w.options..., + ) +} -// func (w *walletWithOptions) IssueImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// options ...common.Option, -// ) (*evm.Tx, error) { -// return w.Wallet.IssueImportTx( -// chainID, -// to, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueImportTx( + chainID ids.ID, + to ethcommon.Address, + options ...common.Option, +) (*evm.Tx, error) { + return w.Wallet.IssueImportTx( + chainID, + to, + common.UnionOptions(w.options, options)..., + ) +} -// func (w *walletWithOptions) IssueExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// options ...common.Option, -// ) (*evm.Tx, error) { -// return w.Wallet.IssueExportTx( -// chainID, -// outputs, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + options ...common.Option, +) (*evm.Tx, error) { + return w.Wallet.IssueExportTx( + chainID, + outputs, + common.UnionOptions(w.options, options)..., + ) +} -// func (w *walletWithOptions) IssueUnsignedAtomicTx( -// utx evm.UnsignedAtomicTx, -// options ...common.Option, -// ) (*evm.Tx, error) { -// return w.Wallet.IssueUnsignedAtomicTx( -// utx, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueUnsignedAtomicTx( + utx evm.UnsignedAtomicTx, + options ...common.Option, +) (*evm.Tx, error) { + return w.Wallet.IssueUnsignedAtomicTx( + utx, + common.UnionOptions(w.options, options)..., + ) +} -// func (w *walletWithOptions) IssueAtomicTx( -// tx *evm.Tx, -// options ...common.Option, -// ) error { -// return w.Wallet.IssueAtomicTx( -// tx, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueAtomicTx( + tx *evm.Tx, + options ...common.Option, +) error { + return w.Wallet.IssueAtomicTx( + tx, + common.UnionOptions(w.options, options)..., + ) +} diff --git a/wallet/subnet/primary/api.go b/wallet/subnet/primary/api.go index 3260c05a0a1b..3ac72c217884 100644 --- a/wallet/subnet/primary/api.go +++ b/wallet/subnet/primary/api.go @@ -5,6 +5,12 @@ package primary import ( "context" + "fmt" + + "github.com/ava-labs/coreth/ethclient" + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ethereum/go-ethereum/common" "github.com/ava-labs/avalanchego/api/info" "github.com/ava-labs/avalanchego/codec" @@ -16,6 +22,7 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm" "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" ) @@ -52,9 +59,9 @@ type AVAXState struct { PCTX p.Context XClient avm.Client XCTX x.Context - // CClient evm.Client - // CCTX c.Context - UTXOs UTXOs + CClient evm.Client + CCTX c.Context + UTXOs UTXOs } func FetchState( @@ -68,7 +75,7 @@ func FetchState( infoClient := info.NewClient(uri) pClient := platformvm.NewClient(uri) xClient := avm.NewClient(uri, "X") - // cClient := evm.NewCChainClient(uri) + cClient := evm.NewCChainClient(uri) pCTX, err := p.NewContextFromClients(ctx, infoClient, xClient) if err != nil { @@ -80,10 +87,10 @@ func FetchState( return nil, err } - // cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) - // if err != nil { - // return nil, err - // } + cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) + if err != nil { + return nil, err + } utxos := NewUTXOs() addrList := addrs.List() @@ -102,11 +109,11 @@ func FetchState( client: xClient, codec: x.Parser.Codec(), }, - // { - // id: cCTX.BlockchainID(), - // client: cClient, - // codec: evm.Codec, - // }, + { + id: cCTX.BlockchainID(), + client: cClient, + codec: evm.Codec, + }, } for _, destinationChain := range chains { for _, sourceChain := range chains { @@ -129,52 +136,52 @@ func FetchState( PCTX: pCTX, XClient: xClient, XCTX: xCTX, - // CClient: cClient, - // CCTX: cCTX, - UTXOs: utxos, + CClient: cClient, + CCTX: cCTX, + UTXOs: utxos, }, nil } -// type EthState struct { -// Client ethclient.Client -// Accounts map[common.Address]*c.Account -// } - -// func FetchEthState( -// ctx context.Context, -// uri string, -// addrs set.Set[common.Address], -// ) (*EthState, error) { -// path := fmt.Sprintf( -// "%s/ext/%s/C/rpc", -// uri, -// constants.ChainAliasPrefix, -// ) -// client, err := ethclient.Dial(path) -// if err != nil { -// return nil, err -// } - -// accounts := make(map[common.Address]*c.Account, addrs.Len()) -// for addr := range addrs { -// balance, err := client.BalanceAt(ctx, addr, nil) -// if err != nil { -// return nil, err -// } -// nonce, err := client.NonceAt(ctx, addr, nil) -// if err != nil { -// return nil, err -// } -// accounts[addr] = &c.Account{ -// Balance: balance, -// Nonce: nonce, -// } -// } -// return &EthState{ -// Client: client, -// Accounts: accounts, -// }, nil -// } +type EthState struct { + Client ethclient.Client + Accounts map[common.Address]*c.Account +} + +func FetchEthState( + ctx context.Context, + uri string, + addrs set.Set[common.Address], +) (*EthState, error) { + path := fmt.Sprintf( + "%s/ext/%s/C/rpc", + uri, + constants.ChainAliasPrefix, + ) + client, err := ethclient.Dial(path) + if err != nil { + return nil, err + } + + accounts := make(map[common.Address]*c.Account, addrs.Len()) + for addr := range addrs { + balance, err := client.BalanceAt(ctx, addr, nil) + if err != nil { + return nil, err + } + nonce, err := client.NonceAt(ctx, addr, nil) + if err != nil { + return nil, err + } + accounts[addr] = &c.Account{ + Balance: balance, + Nonce: nonce, + } + } + return &EthState{ + Client: client, + Accounts: accounts, + }, nil +} // AddAllUTXOs fetches all the UTXOs referenced by [addresses] that were sent // from [sourceChainID] to [destinationChainID] from the [client]. It then uses diff --git a/wallet/subnet/primary/example_test.go b/wallet/subnet/primary/example_test.go index 4a73e8c070b2..483c049d4ac0 100644 --- a/wallet/subnet/primary/example_test.go +++ b/wallet/subnet/primary/example_test.go @@ -30,7 +30,7 @@ func ExampleWallet() { wallet, err := MakeWallet(ctx, &WalletConfig{ URI: LocalAPIURI, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet with: %s\n", err) diff --git a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go index 21c081d2982b..d5e8ce422307 100644 --- a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go @@ -46,9 +46,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/add-primary-validator/main.go b/wallet/subnet/primary/examples/add-primary-validator/main.go index 13c28f995f63..a56dae23db3a 100644 --- a/wallet/subnet/primary/examples/add-primary-validator/main.go +++ b/wallet/subnet/primary/examples/add-primary-validator/main.go @@ -45,7 +45,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/c-chain-export/main.go b/wallet/subnet/primary/examples/c-chain-export/main.go index a6b9a0c810b8..fec55c899feb 100644 --- a/wallet/subnet/primary/examples/c-chain-export/main.go +++ b/wallet/subnet/primary/examples/c-chain-export/main.go @@ -3,70 +3,70 @@ package main -// import ( -// "context" -// "log" -// "time" +import ( + "context" + "log" + "time" -// "github.com/ava-labs/avalanchego/genesis" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary" -// ) + "github.com/ava-labs/avalanchego/genesis" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary" +) -// func main() { -// key := genesis.EWOQKey -// uri := primary.LocalAPIURI -// kc := secp256k1fx.NewKeychain(key) -// avaxAddr := key.Address() +func main() { + key := genesis.EWOQKey + uri := primary.LocalAPIURI + kc := secp256k1fx.NewKeychain(key) + avaxAddr := key.Address() -// ctx := context.Background() + ctx := context.Background() -// // MakeWallet fetches the available UTXOs owned by [kc] on the network that -// // [uri] is hosting. -// walletSyncStartTime := time.Now() -// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ -// URI: uri, -// AVAXKeychain: kc, -// EthKeychain: kc, -// }) -// if err != nil { -// log.Fatalf("failed to initialize wallet: %s\n", err) -// } -// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) + // MakeWallet fetches the available UTXOs owned by [kc] on the network that + // [uri] is hosting. + walletSyncStartTime := time.Now() + wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, + }) + if err != nil { + log.Fatalf("failed to initialize wallet: %s\n", err) + } + log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) -// // Get the P-chain wallet -// pWallet := wallet.P() -// cWallet := wallet.C() + // Get the P-chain wallet + pWallet := wallet.P() + cWallet := wallet.C() -// // Pull out useful constants to use when issuing transactions. -// cChainID := cWallet.BlockchainID() -// owner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// avaxAddr, -// }, -// } + // Pull out useful constants to use when issuing transactions. + cChainID := cWallet.BlockchainID() + owner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + avaxAddr, + }, + } -// exportStartTime := time.Now() -// exportTx, err := cWallet.IssueExportTx( -// constants.PlatformChainID, -// []*secp256k1fx.TransferOutput{{ -// Amt: units.Avax, -// OutputOwners: owner, -// }}, -// ) -// if err != nil { -// log.Fatalf("failed to issue export transaction: %s\n", err) -// } -// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) + exportStartTime := time.Now() + exportTx, err := cWallet.IssueExportTx( + constants.PlatformChainID, + []*secp256k1fx.TransferOutput{{ + Amt: units.Avax, + OutputOwners: owner, + }}, + ) + if err != nil { + log.Fatalf("failed to issue export transaction: %s\n", err) + } + log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) -// importStartTime := time.Now() -// importTx, err := pWallet.IssueImportTx(cChainID, &owner) -// if err != nil { -// log.Fatalf("failed to issue import transaction: %s\n", err) -// } -// log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) -// } + importStartTime := time.Now() + importTx, err := pWallet.IssueImportTx(cChainID, &owner) + if err != nil { + log.Fatalf("failed to issue import transaction: %s\n", err) + } + log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) +} diff --git a/wallet/subnet/primary/examples/c-chain-import/main.go b/wallet/subnet/primary/examples/c-chain-import/main.go index 2d9b8a244cb0..b4dc4e603eb3 100644 --- a/wallet/subnet/primary/examples/c-chain-import/main.go +++ b/wallet/subnet/primary/examples/c-chain-import/main.go @@ -3,75 +3,75 @@ package main -// import ( -// "context" -// "log" -// "time" +import ( + "context" + "log" + "time" -// "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/coreth/plugin/evm" -// "github.com/ava-labs/avalanchego/genesis" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary" -// ) + "github.com/ava-labs/avalanchego/genesis" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary" +) -// func main() { -// key := genesis.EWOQKey -// uri := primary.LocalAPIURI -// kc := secp256k1fx.NewKeychain(key) -// avaxAddr := key.Address() -// ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) +func main() { + key := genesis.EWOQKey + uri := primary.LocalAPIURI + kc := secp256k1fx.NewKeychain(key) + avaxAddr := key.Address() + ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) -// ctx := context.Background() + ctx := context.Background() -// // MakeWallet fetches the available UTXOs owned by [kc] on the network that -// // [uri] is hosting. -// walletSyncStartTime := time.Now() -// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ -// URI: uri, -// AVAXKeychain: kc, -// EthKeychain: kc, -// }) -// if err != nil { -// log.Fatalf("failed to initialize wallet: %s\n", err) -// } -// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) + // MakeWallet fetches the available UTXOs owned by [kc] on the network that + // [uri] is hosting. + walletSyncStartTime := time.Now() + wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, + }) + if err != nil { + log.Fatalf("failed to initialize wallet: %s\n", err) + } + log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) -// // Get the P-chain wallet -// pWallet := wallet.P() -// cWallet := wallet.C() + // Get the P-chain wallet + pWallet := wallet.P() + cWallet := wallet.C() -// // Pull out useful constants to use when issuing transactions. -// cChainID := cWallet.BlockchainID() -// avaxAssetID := cWallet.AVAXAssetID() -// owner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// avaxAddr, -// }, -// } + // Pull out useful constants to use when issuing transactions. + cChainID := cWallet.BlockchainID() + avaxAssetID := cWallet.AVAXAssetID() + owner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + avaxAddr, + }, + } -// exportStartTime := time.Now() -// exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ -// Asset: avax.Asset{ID: avaxAssetID}, -// Out: &secp256k1fx.TransferOutput{ -// Amt: units.Avax, -// OutputOwners: owner, -// }, -// }}) -// if err != nil { -// log.Fatalf("failed to issue export transaction: %s\n", err) -// } -// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) + exportStartTime := time.Now() + exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ + Asset: avax.Asset{ID: avaxAssetID}, + Out: &secp256k1fx.TransferOutput{ + Amt: units.Avax, + OutputOwners: owner, + }, + }}) + if err != nil { + log.Fatalf("failed to issue export transaction: %s\n", err) + } + log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) -// importStartTime := time.Now() -// importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) -// if err != nil { -// log.Fatalf("failed to issue import transaction: %s\n", err) -// } -// log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) -// } + importStartTime := time.Now() + importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) + if err != nil { + log.Fatalf("failed to issue import transaction: %s\n", err) + } + log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) +} diff --git a/wallet/subnet/primary/examples/create-asset/main.go b/wallet/subnet/primary/examples/create-asset/main.go index 0bccfbb5fc52..30804f083df6 100644 --- a/wallet/subnet/primary/examples/create-asset/main.go +++ b/wallet/subnet/primary/examples/create-asset/main.go @@ -30,7 +30,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-chain/main.go b/wallet/subnet/primary/examples/create-chain/main.go index 521a3cca53cf..5e6898a1b649 100644 --- a/wallet/subnet/primary/examples/create-chain/main.go +++ b/wallet/subnet/primary/examples/create-chain/main.go @@ -41,9 +41,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/create-locked-stakeable/main.go b/wallet/subnet/primary/examples/create-locked-stakeable/main.go index 92f1b5cb0e1b..e688968e9e8a 100644 --- a/wallet/subnet/primary/examples/create-locked-stakeable/main.go +++ b/wallet/subnet/primary/examples/create-locked-stakeable/main.go @@ -39,7 +39,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-subnet/main.go b/wallet/subnet/primary/examples/create-subnet/main.go index 3e8d69bc016a..add98ea7931c 100644 --- a/wallet/subnet/primary/examples/create-subnet/main.go +++ b/wallet/subnet/primary/examples/create-subnet/main.go @@ -28,7 +28,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/remove-subnet-validator/main.go b/wallet/subnet/primary/examples/remove-subnet-validator/main.go index 46f4b85124db..2842c7c0a790 100644 --- a/wallet/subnet/primary/examples/remove-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/remove-subnet-validator/main.go @@ -38,9 +38,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/wallet.go b/wallet/subnet/primary/wallet.go index de50d12f866b..54de390d029c 100644 --- a/wallet/subnet/primary/wallet.go +++ b/wallet/subnet/primary/wallet.go @@ -11,6 +11,7 @@ import ( "github.com/ava-labs/avalanchego/utils/crypto/keychain" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" @@ -22,13 +23,13 @@ var _ Wallet = (*wallet)(nil) type Wallet interface { P() p.Wallet X() x.Wallet - // C() c.Wallet + C() c.Wallet } type wallet struct { p p.Wallet x x.Wallet - // c c.Wallet + c c.Wallet } func (w *wallet) P() p.Wallet { @@ -39,16 +40,16 @@ func (w *wallet) X() x.Wallet { return w.x } -// func (w *wallet) C() c.Wallet { -// return w.c -// } +func (w *wallet) C() c.Wallet { + return w.c +} // Creates a new default wallet -func NewWallet(p p.Wallet, x x.Wallet /*, c c.Wallet*/) Wallet { +func NewWallet(p p.Wallet, x x.Wallet, c c.Wallet) Wallet { return &wallet{ p: p, x: x, - // c: c, + c: c, } } @@ -57,7 +58,7 @@ func NewWalletWithOptions(w Wallet, options ...common.Option) Wallet { return NewWallet( p.NewWalletWithOptions(w.P(), options...), x.NewWalletWithOptions(w.X(), options...), - // c.NewWalletWithOptions(w.C(), options...), + c.NewWalletWithOptions(w.C(), options...), ) } @@ -66,7 +67,7 @@ type WalletConfig struct { URI string // required // Keys to use for signing all transactions. AVAXKeychain keychain.Keychain // required - // EthKeychain c.EthKeychain // required + EthKeychain c.EthKeychain // required // Set of P-chain transactions that the wallet should know about to be able // to generate transactions. PChainTxs map[ids.ID]*txs.Tx // optional @@ -92,11 +93,11 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { return nil, err } - // ethAddrs := config.EthKeychain.EthAddresses() - // ethState, err := FetchEthState(ctx, config.URI, ethAddrs) - // if err != nil { - // return nil, err - // } + ethAddrs := config.EthKeychain.EthAddresses() + ethState, err := FetchEthState(ctx, config.URI, ethAddrs) + if err != nil { + return nil, err + } pChainTxs := config.PChainTxs if pChainTxs == nil { @@ -126,15 +127,15 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { xBuilder := x.NewBuilder(avaxAddrs, xBackend) xSigner := x.NewSigner(config.AVAXKeychain, xBackend) - // cChainID := avaxState.CCTX.BlockchainID() - // cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) - // cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) - // cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) - // cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) + cChainID := avaxState.CCTX.BlockchainID() + cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) + cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) + cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) + cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) return NewWallet( p.NewWallet(pBuilder, pSigner, avaxState.PClient, pBackend), x.NewWallet(xBuilder, xSigner, avaxState.XClient, xBackend), - // c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), + c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), ), nil } From 834f99ddb24593c4c267dfe9d367537c4aaa8249 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Sat, 4 Nov 2023 16:48:29 +0100 Subject: [PATCH 29/36] introduced backfilling internal error --- .../engine/snowman/block/state_syncable_vm.go | 2 + .../snowman/syncer/blocks_backfiller.go | 7 ++ .../transitive_block_backfilling_test.go | 93 ++++++++++++++++++- 3 files changed, 101 insertions(+), 1 deletion(-) diff --git a/snow/engine/snowman/block/state_syncable_vm.go b/snow/engine/snowman/block/state_syncable_vm.go index 811d6f3b19d2..c4bfaf7aa69e 100644 --- a/snow/engine/snowman/block/state_syncable_vm.go +++ b/snow/engine/snowman/block/state_syncable_vm.go @@ -14,6 +14,7 @@ var ( ErrStateSyncableVMNotImplemented = errors.New("vm does not implement StateSyncableVM interface") ErrBlockBackfillingNotEnabled = errors.New("vm does not require block backfilling") ErrStopBlockBackfilling = errors.New("vm required stopping block backfilling") + ErrInternalBlockBackfilling = errors.New("block backfilling internal error") ) // StateSyncableVM contains the functionality to allow VMs to sync to a given @@ -62,6 +63,7 @@ type StateSyncableVM interface { // BackfillBlocks returns the next block ID to be requested and an error // Returns the ID and height of the block it wants to start backfilling from. // Returns [ErrStopBlockBackfilling] if VM has done backfilling; engine will stop requesting blocks. + // Returns [ErrInternalBlockBackfilling] if VM has erred in a way that should make block backfilling fail. // If BackfillBlocks returns any other error, engine will issue a GetAncestor call to a different peer // with the previously requested block ID BackfillBlocks(ctx context.Context, blocks [][]byte) (ids.ID, uint64, error) diff --git a/snow/engine/snowman/syncer/blocks_backfiller.go b/snow/engine/snowman/syncer/blocks_backfiller.go index 94964644250d..2e4fc6137a60 100644 --- a/snow/engine/snowman/syncer/blocks_backfiller.go +++ b/snow/engine/snowman/syncer/blocks_backfiller.go @@ -124,6 +124,13 @@ func (bb *BlockBackfiller) Ancestors(ctx context.Context, nodeID ids.NodeID, req bb.Ctx.Log.Info("block backfilling done") bb.Ctx.StateSyncing.Set(false) return nil + case err == block.ErrInternalBlockBackfilling: + bb.Ctx.Log.Debug("internal error while backfilling blocks", + zap.Stringer("nodeID", nodeID), + zap.Uint32("requestID", requestID), + zap.Error(err), + ) + return err case err != nil: bb.Ctx.Log.Debug("failed to backfill blocks in Ancestors", zap.Stringer("nodeID", nodeID), diff --git a/snow/engine/snowman/transitive_block_backfilling_test.go b/snow/engine/snowman/transitive_block_backfilling_test.go index bb74ea3b4181..2f4dd85cf584 100644 --- a/snow/engine/snowman/transitive_block_backfilling_test.go +++ b/snow/engine/snowman/transitive_block_backfilling_test.go @@ -280,7 +280,7 @@ func TestGetAncestorsFailedProcessing(t *testing.T) { } } -func TestBackfillingTerminatedByVM(t *testing.T) { +func TestBackfillingTerminatedCleanlyByVM(t *testing.T) { require := require.New(t) engCfg, vm, sender, err := setupBlockBackfillingTests(t) @@ -389,6 +389,97 @@ func TestBackfillingTerminatedByVM(t *testing.T) { } } +func TestBackfillingTerminatedWithErrorByVM(t *testing.T) { + require := require.New(t) + + engCfg, vm, sender, err := setupBlockBackfillingTests(t) + require.NoError(err) + + // create the engine + te, err := newTransitive(engCfg) + require.NoError(err) + + // for current test we need a single validator. Disconnect the other + dummyCtx := context.Background() + require.NoError(te.Disconnected(dummyCtx, engCfg.Validators.GetValidatorIDs(engCfg.Ctx.SubnetID)[1])) + + // enable block backfilling + reqBlkFirst := ids.GenerateTestID() + dummyHeight := uint64(1492) + vm.BackfillBlocksEnabledF = func(ctx context.Context) (ids.ID, uint64, error) { + return reqBlkFirst, dummyHeight, nil + } + + // start the engine + startReqNum := uint32(0) + require.NoError(te.Start(dummyCtx, startReqNum)) + + var ( + nodeID = engCfg.Validators.GetValidatorIDs(engCfg.Ctx.SubnetID)[0] + responseReqID = startReqNum + blkBytes = [][]byte{{1}} // content does not matter here. We just need it non-empty + + pushedBlks = false + nextRequestedBlk = ids.GenerateTestID() + issuedBlk = ids.Empty + ) + + // 1. Successfully request and download some blocks + { + responseReqID++ + vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, uint64, error) { + pushedBlks = true + return nextRequestedBlk, dummyHeight, nil // requestedBlkID does not really matter here + } + sender.SendGetAncestorsF = func(ctx context.Context, ni ids.NodeID, u uint32, blkID ids.ID) { + issuedBlk = blkID + } + require.NoError(te.Ancestors(dummyCtx, nodeID, responseReqID, blkBytes)) + require.True(pushedBlks) + require.Equal(nextRequestedBlk, issuedBlk) + } + + // 2. Successfully request and download some more blocks + { + pushedBlks = false + nextRequestedBlk = ids.GenerateTestID() + issuedBlk = ids.Empty + responseReqID++ + + vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, uint64, error) { + pushedBlks = true + return nextRequestedBlk, dummyHeight, nil // requestedBlkID does not really matter here + } + sender.SendGetAncestorsF = func(ctx context.Context, ni ids.NodeID, u uint32, blkID ids.ID) { + issuedBlk = blkID + } + + require.NoError(te.Ancestors(dummyCtx, nodeID, responseReqID, blkBytes)) + require.True(pushedBlks) + require.Equal(nextRequestedBlk, issuedBlk) + } + + // 3. Let the VM have an internal error while processing backfilled blocks. + { + issuedBlkRequest := false + pushedBlks = false + responseReqID++ + + vm.BackfillBlocksF = func(ctx context.Context, b [][]byte) (ids.ID, uint64, error) { + pushedBlks = true + return ids.Empty, dummyHeight, block.ErrInternalBlockBackfilling + } + sender.SendGetAncestorsF = func(ctx context.Context, ni ids.NodeID, u uint32, blkID ids.ID) { + issuedBlkRequest = true + } + + err := te.Ancestors(dummyCtx, nodeID, responseReqID, blkBytes) + require.ErrorIs(err, block.ErrInternalBlockBackfilling) + require.True(pushedBlks) + require.False(issuedBlkRequest) // no more requests, block backfilling done + } +} + type fullVM struct { *block.TestVM *block.TestStateSyncableVM From 5269013048cc3b9db9c1734524ae366d458976a7 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Sun, 5 Nov 2023 18:03:53 +0100 Subject: [PATCH 30/36] improved error checking --- snow/engine/snowman/syncer/blocks_backfiller.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/snow/engine/snowman/syncer/blocks_backfiller.go b/snow/engine/snowman/syncer/blocks_backfiller.go index 2e4fc6137a60..9913ae5cda4e 100644 --- a/snow/engine/snowman/syncer/blocks_backfiller.go +++ b/snow/engine/snowman/syncer/blocks_backfiller.go @@ -65,7 +65,7 @@ func (bb *BlockBackfiller) Start(ctx context.Context) error { } switch wantedBlk, _, err := ssVM.BackfillBlocksEnabled(ctx); { - case err == block.ErrBlockBackfillingNotEnabled: + case errors.Is(err, block.ErrBlockBackfillingNotEnabled): bb.Ctx.Log.Info("block backfilling not enabled") bb.Ctx.StateSyncing.Set(false) return nil @@ -120,11 +120,11 @@ func (bb *BlockBackfiller) Ancestors(ctx context.Context, nodeID ids.NodeID, req } switch nextWantedBlkID, _, err := ssVM.BackfillBlocks(ctx, blks); { - case err == block.ErrStopBlockBackfilling: + case errors.Is(err, block.ErrStopBlockBackfilling): bb.Ctx.Log.Info("block backfilling done") bb.Ctx.StateSyncing.Set(false) return nil - case err == block.ErrInternalBlockBackfilling: + case errors.Is(err, block.ErrInternalBlockBackfilling): bb.Ctx.Log.Debug("internal error while backfilling blocks", zap.Stringer("nodeID", nodeID), zap.Uint32("requestID", requestID), From a2464ebe72bc9a022e0356587d686867bdc7c326 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 2 Nov 2023 19:16:48 +0100 Subject: [PATCH 31/36] temporarily cut coreth dependencies --- go.mod | 25 - go.sum | 76 -- node/node.go | 4 +- tests/e2e/c/dynamic_fees.go | 326 +++---- tests/e2e/c/interchain_workflow.go | 320 +++---- tests/e2e/e2e.go | 114 ++- tests/e2e/p/interchain_workflow.go | 444 +++++----- tests/e2e/x/interchain_workflow.go | 296 +++---- tests/fixture/testnet/config.go | 54 +- vms/example/xsvm/cmd/chain/create/cmd.go | 6 +- wallet/chain/c/backend.go | 300 +++---- wallet/chain/c/builder.go | 792 +++++++++--------- wallet/chain/c/builder_with_options.go | 136 +-- wallet/chain/c/context.go | 130 +-- wallet/chain/c/signer.go | 436 +++++----- wallet/chain/c/wallet.go | 402 ++++----- wallet/chain/c/wallet_with_options.go | 134 +-- wallet/subnet/primary/api.go | 119 ++- wallet/subnet/primary/example_test.go | 2 +- .../add-permissioned-subnet-validator/main.go | 6 +- .../examples/add-primary-validator/main.go | 2 +- .../primary/examples/c-chain-export/main.go | 118 +-- .../primary/examples/c-chain-import/main.go | 126 +-- .../primary/examples/create-asset/main.go | 2 +- .../primary/examples/create-chain/main.go | 6 +- .../examples/create-locked-stakeable/main.go | 2 +- .../primary/examples/create-subnet/main.go | 2 +- .../examples/remove-subnet-validator/main.go | 6 +- wallet/subnet/primary/wallet.go | 41 +- 29 files changed, 2153 insertions(+), 2274 deletions(-) diff --git a/go.mod b/go.mod index 0c161de4a463..d88ed76f20e2 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,6 @@ require ( github.com/DataDog/zstd v1.5.2 github.com/Microsoft/go-winio v0.5.2 github.com/NYTimes/gziphandler v1.1.1 - github.com/ava-labs/coreth v0.12.8-rc.1 github.com/ava-labs/ledger-avalanche/go v0.0.0-20231102202641-ae2ebdaeac34 github.com/btcsuite/btcd/btcutil v1.1.3 github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 @@ -75,7 +74,6 @@ require ( github.com/BurntSushi/toml v1.2.1 // indirect github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect - github.com/VictoriaMetrics/fastcache v1.10.0 // indirect github.com/benbjohnson/clock v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect @@ -84,44 +82,26 @@ require ( github.com/cockroachdb/errors v1.9.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/redact v1.1.3 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/deckarep/golang-set/v2 v2.1.0 // indirect - github.com/dlclark/regexp2 v1.7.0 // indirect - github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect - github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/frankban/quicktest v1.14.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect - github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect - github.com/go-stack/stack v1.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect - github.com/google/uuid v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 // indirect - github.com/hashicorp/go-bexpr v0.1.10 // indirect - github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/klauspost/compress v1.15.15 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/magiconair/properties v1.8.6 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/mitchellh/pointerstructure v1.2.0 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect @@ -129,17 +109,12 @@ require ( github.com/prometheus/common v0.39.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sanity-io/litter v1.5.1 // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/status-im/keycard-go v0.2.0 // indirect github.com/subosito/gotenv v1.3.0 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect - github.com/tyler-smith/go-bip39 v1.1.0 // indirect - github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa // indirect - github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/zondax/hid v0.9.2 // indirect github.com/zondax/ledger-go v0.14.3 // indirect diff --git a/go.sum b/go.sum index 164a7e96d6c0..fc0e99dd49fb 100644 --- a/go.sum +++ b/go.sum @@ -56,18 +56,12 @@ github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cq github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= -github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY= -github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/ava-labs/coreth v0.12.8-rc.1 h1:tvJcxQTQzxIQqx8TnrxdyMhZYbdsMaiy6AEiOyjvaa4= -github.com/ava-labs/coreth v0.12.8-rc.1/go.mod h1:GBH5SxHZdScSp95IijDs9+Gxw/QDIWvfoLKiJMNYLsE= github.com/ava-labs/ledger-avalanche/go v0.0.0-20231102202641-ae2ebdaeac34 h1:mg9Uw6oZFJKytJxgxnl3uxZOs/SB8CVHg6Io4Tf99Zc= github.com/ava-labs/ledger-avalanche/go v0.0.0-20231102202641-ae2ebdaeac34/go.mod h1:pJxaT9bUgeRNVmNRgtCHb7sFDIRKy7CzTQVi8gGNT6g= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= @@ -104,18 +98,13 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= @@ -147,16 +136,12 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= -github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= @@ -167,14 +152,6 @@ github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6ps github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= -github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= -github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= -github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= -github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -191,8 +168,6 @@ github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2 github.com/ethereum/go-ethereum v1.12.0/go.mod h1:/oo2X/dZLJjf2mJ6YT9wcWxa4nNJDBKDBU6sFIpx1Gs= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -201,8 +176,6 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= @@ -226,11 +199,7 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= -github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= @@ -315,14 +284,10 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -343,17 +308,11 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 h1:kr3j8iIMR4ywO/O0rvksXaJvauGGCMg2zAZIiNZ9uIQ= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0/go.mod h1:ummNFgdgLhhX7aIiy35vVmQNS0rWXknfPE0qe6fmFXg= -github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= -github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e/go.mod h1:j9cQbcqHQujT0oKJ38PylVfqohClLr3CvDC+Qcg+lhU= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8= @@ -365,7 +324,6 @@ github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3 github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -407,7 +365,6 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -415,7 +372,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= @@ -426,17 +382,11 @@ github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -445,11 +395,8 @@ github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= -github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -468,8 +415,6 @@ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -537,8 +482,6 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sanity-io/litter v1.5.1 h1:dwnrSypP6q56o3lFxTU+t2fwQ9A+U5qrXVO4Qg9KwVU= github.com/sanity-io/litter v1.5.1/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0= @@ -574,8 +517,6 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= -github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= -github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -607,14 +548,10 @@ github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZF github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= -github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= -github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -626,8 +563,6 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1: github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= @@ -637,7 +572,6 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= @@ -736,7 +670,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -782,7 +715,6 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -806,7 +738,6 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -871,12 +802,8 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -893,7 +820,6 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -957,7 +883,6 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1082,7 +1007,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= diff --git a/node/node.go b/node/node.go index d4763db746ec..67d6e63f8bb2 100644 --- a/node/node.go +++ b/node/node.go @@ -25,7 +25,7 @@ import ( "go.uber.org/zap" - coreth "github.com/ava-labs/coreth/plugin/evm" + // coreth "github.com/ava-labs/coreth/plugin/evm" "github.com/ava-labs/avalanchego/api/admin" "github.com/ava-labs/avalanchego/api/auth" @@ -945,7 +945,7 @@ func (n *Node) initVMs() error { CreateAssetTxFee: n.Config.CreateAssetTxFee, }, }), - vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), + // vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), n.VMManager.RegisterFactory(context.TODO(), secp256k1fx.ID, &secp256k1fx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), nftfx.ID, &nftfx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), propertyfx.ID, &propertyfx.Factory{}), diff --git a/tests/e2e/c/dynamic_fees.go b/tests/e2e/c/dynamic_fees.go index c8e005621983..8748dda7451d 100644 --- a/tests/e2e/c/dynamic_fees.go +++ b/tests/e2e/c/dynamic_fees.go @@ -3,166 +3,166 @@ package c -import ( - "math/big" - "strings" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/stretchr/testify/require" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/coreth/core/types" - "github.com/ava-labs/coreth/params" - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/tests" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/tests/fixture/testnet" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -) - -// This test uses the compiled bin for `hashing.sol` as -// well as its ABI contained in `hashing_contract.go`. - -var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { - require := require.New(ginkgo.GinkgoT()) - - // Need a gas limit much larger than the standard 21_000 to enable - // the contract to induce a gas price increase - const largeGasLimit = uint64(8_000_000) - - // TODO(marun) What is the significance of this value? - gasTip := big.NewInt(1000 * params.GWei) - - ginkgo.It("should ensure that the gas price is affected by load", func() { - ginkgo.By("creating a new private network to ensure isolation from other tests") - privateNetwork := e2e.Env.NewPrivateNetwork() - - ginkgo.By("allocating a pre-funded key") - key := privateNetwork.GetConfig().FundedKeys[0] - ethAddress := evm.GetEthAddress(key) - - ginkgo.By("initializing a coreth client") - node := privateNetwork.GetNodes()[0] - nodeURI := testnet.NodeURI{ - NodeID: node.GetID(), - URI: node.GetProcessContext().URI, - } - ethClient := e2e.NewEthClient(nodeURI) - - ginkgo.By("initializing a transaction signer") - cChainID, err := ethClient.ChainID(e2e.DefaultContext()) - require.NoError(err) - signer := types.NewEIP155Signer(cChainID) - ecdsaKey := key.ToECDSA() - sign := func(tx *types.Transaction) *types.Transaction { - signedTx, err := types.SignTx(tx, signer, ecdsaKey) - require.NoError(err) - return signedTx - } - - var contractAddress common.Address - ginkgo.By("deploying an expensive contract", func() { - // Create transaction - nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) - require.NoError(err) - compiledContract := common.Hex2Bytes(hashingCompiledContract) - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - GasPrice: gasTip, - Gas: largeGasLimit, - Value: common.Big0, - Data: compiledContract, - }) - - // Send the transaction and wait for acceptance - signedTx := sign(tx) - receipt := e2e.SendEthTransaction(ethClient, signedTx) - - contractAddress = receipt.ContractAddress - }) - - var gasPrice *big.Int - ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { - // Evaluate the bytes representation of the contract - hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) - require.NoError(err) - contractData, err := hashingABI.Pack("hashIt") - require.NoError(err) - - var initialGasPrice *big.Int - e2e.Eventually(func() bool { - // Check the gas price - var err error - gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) - require.NoError(err) - if initialGasPrice == nil { - initialGasPrice = gasPrice - tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) - } else if gasPrice.Cmp(initialGasPrice) > 0 { - // Gas price has increased - tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) - return true - } - - // Create the transaction - nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) - require.NoError(err) - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - GasPrice: gasTip, - Gas: largeGasLimit, - To: &contractAddress, - Value: common.Big0, - Data: contractData, - }) - - // Send the transaction and wait for acceptance - signedTx := sign(tx) - _ = e2e.SendEthTransaction(ethClient, signedTx) - - // The gas price will be checked at the start of the next iteration - return false - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") - }) - - ginkgo.By("waiting for the gas price to decrease...", func() { - initialGasPrice := gasPrice - e2e.Eventually(func() bool { - var err error - gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) - require.NoError(err) - tests.Outf("{{blue}}.{{/}}") - return initialGasPrice.Cmp(gasPrice) > 0 - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") - tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) - }) - - ginkgo.By("sending funds at the current gas price", func() { - // Create a recipient address - recipientKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - recipientEthAddress := evm.GetEthAddress(recipientKey) - - // Create transaction - nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) - require.NoError(err) - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - GasPrice: gasPrice, - Gas: e2e.DefaultGasLimit, - To: &recipientEthAddress, - Value: common.Big0, - }) - - // Send the transaction and wait for acceptance - signedTx := sign(tx) - _ = e2e.SendEthTransaction(ethClient, signedTx) - }) - - e2e.CheckBootstrapIsPossible(privateNetwork) - }) -}) +// import ( +// "math/big" +// "strings" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/stretchr/testify/require" + +// "github.com/ethereum/go-ethereum/accounts/abi" +// "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/coreth/core/types" +// "github.com/ava-labs/coreth/params" +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/tests" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/tests/fixture/testnet" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// ) + +// // This test uses the compiled bin for `hashing.sol` as +// // well as its ABI contained in `hashing_contract.go`. + +// var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { +// require := require.New(ginkgo.GinkgoT()) + +// // Need a gas limit much larger than the standard 21_000 to enable +// // the contract to induce a gas price increase +// const largeGasLimit = uint64(8_000_000) + +// // TODO(marun) What is the significance of this value? +// gasTip := big.NewInt(1000 * params.GWei) + +// ginkgo.It("should ensure that the gas price is affected by load", func() { +// ginkgo.By("creating a new private network to ensure isolation from other tests") +// privateNetwork := e2e.Env.NewPrivateNetwork() + +// ginkgo.By("allocating a pre-funded key") +// key := privateNetwork.GetConfig().FundedKeys[0] +// ethAddress := evm.GetEthAddress(key) + +// ginkgo.By("initializing a coreth client") +// node := privateNetwork.GetNodes()[0] +// nodeURI := testnet.NodeURI{ +// NodeID: node.GetID(), +// URI: node.GetProcessContext().URI, +// } +// ethClient := e2e.NewEthClient(nodeURI) + +// ginkgo.By("initializing a transaction signer") +// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) +// require.NoError(err) +// signer := types.NewEIP155Signer(cChainID) +// ecdsaKey := key.ToECDSA() +// sign := func(tx *types.Transaction) *types.Transaction { +// signedTx, err := types.SignTx(tx, signer, ecdsaKey) +// require.NoError(err) +// return signedTx +// } + +// var contractAddress common.Address +// ginkgo.By("deploying an expensive contract", func() { +// // Create transaction +// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) +// require.NoError(err) +// compiledContract := common.Hex2Bytes(hashingCompiledContract) +// tx := types.NewTx(&types.LegacyTx{ +// Nonce: nonce, +// GasPrice: gasTip, +// Gas: largeGasLimit, +// Value: common.Big0, +// Data: compiledContract, +// }) + +// // Send the transaction and wait for acceptance +// signedTx := sign(tx) +// receipt := e2e.SendEthTransaction(ethClient, signedTx) + +// contractAddress = receipt.ContractAddress +// }) + +// var gasPrice *big.Int +// ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { +// // Evaluate the bytes representation of the contract +// hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) +// require.NoError(err) +// contractData, err := hashingABI.Pack("hashIt") +// require.NoError(err) + +// var initialGasPrice *big.Int +// e2e.Eventually(func() bool { +// // Check the gas price +// var err error +// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) +// require.NoError(err) +// if initialGasPrice == nil { +// initialGasPrice = gasPrice +// tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) +// } else if gasPrice.Cmp(initialGasPrice) > 0 { +// // Gas price has increased +// tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) +// return true +// } + +// // Create the transaction +// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) +// require.NoError(err) +// tx := types.NewTx(&types.LegacyTx{ +// Nonce: nonce, +// GasPrice: gasTip, +// Gas: largeGasLimit, +// To: &contractAddress, +// Value: common.Big0, +// Data: contractData, +// }) + +// // Send the transaction and wait for acceptance +// signedTx := sign(tx) +// _ = e2e.SendEthTransaction(ethClient, signedTx) + +// // The gas price will be checked at the start of the next iteration +// return false +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") +// }) + +// ginkgo.By("waiting for the gas price to decrease...", func() { +// initialGasPrice := gasPrice +// e2e.Eventually(func() bool { +// var err error +// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) +// require.NoError(err) +// tests.Outf("{{blue}}.{{/}}") +// return initialGasPrice.Cmp(gasPrice) > 0 +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") +// tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) +// }) + +// ginkgo.By("sending funds at the current gas price", func() { +// // Create a recipient address +// recipientKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) +// recipientEthAddress := evm.GetEthAddress(recipientKey) + +// // Create transaction +// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) +// require.NoError(err) +// tx := types.NewTx(&types.LegacyTx{ +// Nonce: nonce, +// GasPrice: gasPrice, +// Gas: e2e.DefaultGasLimit, +// To: &recipientEthAddress, +// Value: common.Big0, +// }) + +// // Send the transaction and wait for acceptance +// signedTx := sign(tx) +// _ = e2e.SendEthTransaction(ethClient, signedTx) +// }) + +// e2e.CheckBootstrapIsPossible(privateNetwork) +// }) +// }) diff --git a/tests/e2e/c/interchain_workflow.go b/tests/e2e/c/interchain_workflow.go index d4881255ddff..8c019078ec6c 100644 --- a/tests/e2e/c/interchain_workflow.go +++ b/tests/e2e/c/interchain_workflow.go @@ -3,163 +3,163 @@ package c -import ( - "math/big" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/coreth/core/types" - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { - require := require.New(ginkgo.GinkgoT()) - - const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer - - ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { - ginkgo.By("initializing a new eth client") - // Select a random node URI to use for both the eth client and - // the wallet to avoid having to verify that all nodes are at - // the same height before initializing the wallet. - nodeURI := e2e.Env.GetRandomNodeURI() - ethClient := e2e.NewEthClient(nodeURI) - - ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") - senderKey := e2e.Env.AllocateFundedKey() - senderEthAddress := evm.GetEthAddress(senderKey) - recipientKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - recipientEthAddress := evm.GetEthAddress(recipientKey) - - ginkgo.By("sending funds from one address to another on the C-Chain", func() { - // Create transaction - acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) - require.NoError(err) - gasPrice := e2e.SuggestGasPrice(ethClient) - tx := types.NewTransaction( - acceptedNonce, - recipientEthAddress, - big.NewInt(int64(txAmount)), - e2e.DefaultGasLimit, - gasPrice, - nil, - ) - - // Sign transaction - cChainID, err := ethClient.ChainID(e2e.DefaultContext()) - require.NoError(err) - signer := types.NewEIP155Signer(cChainID) - signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) - require.NoError(err) - - _ = e2e.SendEthTransaction(ethClient, signedTx) - - ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") - e2e.Eventually(func() bool { - balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) - require.NoError(err) - return balance.Cmp(big.NewInt(0)) > 0 - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") - }) - - // Wallet must be initialized after sending funds on the - // C-Chain with the same node URI to ensure wallet state - // matches on-chain state. - ginkgo.By("initializing a keychain and associated wallet") - keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) - baseWallet := e2e.NewWallet(keychain, nodeURI) - xWallet := baseWallet.X() - cWallet := baseWallet.C() - pWallet := baseWallet.P() - - ginkgo.By("defining common configuration") - avaxAssetID := xWallet.AVAXAssetID() - // Use the same owner for import funds to X-Chain and P-Chain - recipientOwner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - recipientKey.Address(), - }, - } - // Use the same outputs for both X-Chain and P-Chain exports - exportOutputs := []*secp256k1fx.TransferOutput{ - { - Amt: txAmount, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - keychain.Keys[0].Address(), - }, - }, - }, - } - - ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { - _, err := cWallet.IssueExportTx( - xWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { - _, err := xWallet.IssueImportTx( - cWallet.BlockchainID(), - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { - balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { - _, err := cWallet.IssueExportTx( - constants.PlatformChainID, - exportOutputs, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { - _, err = pWallet.IssueImportTx( - cWallet.BlockchainID(), - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { - balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) - }) -}) +// import ( +// "math/big" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/stretchr/testify/require" + +// "github.com/ava-labs/coreth/core/types" +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { +// require := require.New(ginkgo.GinkgoT()) + +// const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer + +// ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { +// ginkgo.By("initializing a new eth client") +// // Select a random node URI to use for both the eth client and +// // the wallet to avoid having to verify that all nodes are at +// // the same height before initializing the wallet. +// nodeURI := e2e.Env.GetRandomNodeURI() +// ethClient := e2e.NewEthClient(nodeURI) + +// ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") +// senderKey := e2e.Env.AllocateFundedKey() +// senderEthAddress := evm.GetEthAddress(senderKey) +// recipientKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) +// recipientEthAddress := evm.GetEthAddress(recipientKey) + +// ginkgo.By("sending funds from one address to another on the C-Chain", func() { +// // Create transaction +// acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) +// require.NoError(err) +// gasPrice := e2e.SuggestGasPrice(ethClient) +// tx := types.NewTransaction( +// acceptedNonce, +// recipientEthAddress, +// big.NewInt(int64(txAmount)), +// e2e.DefaultGasLimit, +// gasPrice, +// nil, +// ) + +// // Sign transaction +// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) +// require.NoError(err) +// signer := types.NewEIP155Signer(cChainID) +// signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) +// require.NoError(err) + +// _ = e2e.SendEthTransaction(ethClient, signedTx) + +// ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") +// e2e.Eventually(func() bool { +// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) +// require.NoError(err) +// return balance.Cmp(big.NewInt(0)) > 0 +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") +// }) + +// // Wallet must be initialized after sending funds on the +// // C-Chain with the same node URI to ensure wallet state +// // matches on-chain state. +// ginkgo.By("initializing a keychain and associated wallet") +// keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) +// baseWallet := e2e.NewWallet(keychain, nodeURI) +// xWallet := baseWallet.X() +// cWallet := baseWallet.C() +// pWallet := baseWallet.P() + +// ginkgo.By("defining common configuration") +// avaxAssetID := xWallet.AVAXAssetID() +// // Use the same owner for import funds to X-Chain and P-Chain +// recipientOwner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// recipientKey.Address(), +// }, +// } +// // Use the same outputs for both X-Chain and P-Chain exports +// exportOutputs := []*secp256k1fx.TransferOutput{ +// { +// Amt: txAmount, +// OutputOwners: secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// keychain.Keys[0].Address(), +// }, +// }, +// }, +// } + +// ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { +// _, err := cWallet.IssueExportTx( +// xWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { +// _, err := xWallet.IssueImportTx( +// cWallet.BlockchainID(), +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { +// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { +// _, err := cWallet.IssueExportTx( +// constants.PlatformChainID, +// exportOutputs, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { +// _, err = pWallet.IssueImportTx( +// cWallet.BlockchainID(), +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { +// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) +// }) +// }) diff --git a/tests/e2e/e2e.go b/tests/e2e/e2e.go index 44c5d911e8dd..33b219ae4061 100644 --- a/tests/e2e/e2e.go +++ b/tests/e2e/e2e.go @@ -7,23 +7,15 @@ package e2e import ( "context" "encoding/json" - "errors" - "fmt" - "math/big" "math/rand" "os" "path/filepath" - "strings" "time" ginkgo "github.com/onsi/ginkgo/v2" "github.com/stretchr/testify/require" - "github.com/ava-labs/coreth/core/types" - "github.com/ava-labs/coreth/ethclient" - "github.com/ava-labs/coreth/interfaces" - "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/tests" "github.com/ava-labs/avalanchego/tests/fixture" @@ -147,7 +139,7 @@ func NewWallet(keychain *secp256k1fx.Keychain, nodeURI testnet.NodeURI) primary. baseWallet, err := primary.MakeWallet(DefaultContext(), &primary.WalletConfig{ URI: nodeURI.URI, AVAXKeychain: keychain, - EthKeychain: keychain, + // EthKeychain: keychain, }) require.NoError(ginkgo.GinkgoT(), err) return primary.NewWalletWithOptions( @@ -160,15 +152,15 @@ func NewWallet(keychain *secp256k1fx.Keychain, nodeURI testnet.NodeURI) primary. ) } -// Create a new eth client targeting the specified node URI. -func NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { - tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) - nodeAddress := strings.Split(nodeURI.URI, "//")[1] - uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) - client, err := ethclient.Dial(uri) - require.NoError(ginkgo.GinkgoT(), err) - return client -} +// // Create a new eth client targeting the specified node URI. +// func NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { +// tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) +// nodeAddress := strings.Split(nodeURI.URI, "//")[1] +// uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) +// client, err := ethclient.Dial(uri) +// require.NoError(ginkgo.GinkgoT(), err) +// return client +// } // Helper simplifying use of a timed context by canceling the context on ginkgo teardown. func ContextWithTimeout(duration time.Duration) context.Context { @@ -229,49 +221,49 @@ func WaitForHealthy(node testnet.Node) { require.NoError(ginkgo.GinkgoT(), testnet.WaitForHealthy(DefaultContext(), node)) } -// Sends an eth transaction, waits for the transaction receipt to be issued -// and checks that the receipt indicates success. -func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { - require := require.New(ginkgo.GinkgoT()) - - txID := signedTx.Hash() - tests.Outf(" sending eth transaction with ID: %s\n", txID) - - require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) - - // Wait for the receipt - var receipt *types.Receipt - Eventually(func() bool { - var err error - receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) - if errors.Is(err, interfaces.NotFound) { - return false // Transaction is still pending - } - require.NoError(err) - return true - }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") - - require.Equal(receipt.Status, types.ReceiptStatusSuccessful) - return receipt -} - -// Determines the suggested gas price for the configured client that will -// maximize the chances of transaction acceptance. -func SuggestGasPrice(ethClient ethclient.Client) *big.Int { - gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) - require.NoError(ginkgo.GinkgoT(), err) - // Double the suggested gas price to maximize the chances of - // acceptance. Maybe this can be revisited pending resolution of - // https://github.com/ava-labs/coreth/issues/314. - gasPrice.Add(gasPrice, gasPrice) - return gasPrice -} - -// Helper simplifying use via an option of a gas price appropriate for testing. -func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { - baseFee := SuggestGasPrice(ethClient) - return common.WithBaseFee(baseFee) -} +// // Sends an eth transaction, waits for the transaction receipt to be issued +// // and checks that the receipt indicates success. +// func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { +// require := require.New(ginkgo.GinkgoT()) + +// txID := signedTx.Hash() +// tests.Outf(" sending eth transaction with ID: %s\n", txID) + +// require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) + +// // Wait for the receipt +// var receipt *types.Receipt +// Eventually(func() bool { +// var err error +// receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) +// if errors.Is(err, interfaces.NotFound) { +// return false // Transaction is still pending +// } +// require.NoError(err) +// return true +// }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") + +// require.Equal(receipt.Status, types.ReceiptStatusSuccessful) +// return receipt +// } + +// // Determines the suggested gas price for the configured client that will +// // maximize the chances of transaction acceptance. +// func SuggestGasPrice(ethClient ethclient.Client) *big.Int { +// gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) +// require.NoError(ginkgo.GinkgoT(), err) +// // Double the suggested gas price to maximize the chances of +// // acceptance. Maybe this can be revisited pending resolution of +// // https://github.com/ava-labs/coreth/issues/314. +// gasPrice.Add(gasPrice, gasPrice) +// return gasPrice +// } + +// // Helper simplifying use via an option of a gas price appropriate for testing. +// func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { +// baseFee := SuggestGasPrice(ethClient) +// return common.WithBaseFee(baseFee) +// } // Verify that a new node can bootstrap into the network. func CheckBootstrapIsPossible(network testnet.Network) { diff --git a/tests/e2e/p/interchain_workflow.go b/tests/e2e/p/interchain_workflow.go index 9bea416294cb..33a8345f919f 100644 --- a/tests/e2e/p/interchain_workflow.go +++ b/tests/e2e/p/interchain_workflow.go @@ -3,225 +3,225 @@ package p -import ( - "math/big" - "time" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/spf13/cast" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/api/info" - "github.com/ava-labs/avalanchego/config" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/tests/fixture/testnet" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/platformvm/reward" - "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { - require := require.New(ginkgo.GinkgoT()) - - const ( - transferAmount = 10 * units.Avax - weight = 2_000 * units.Avax // Used for both validation and delegation - ) - - ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { - network := e2e.Env.GetNetwork() - - ginkgo.By("checking that the network has a compatible minimum stake duration", func() { - minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) - require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) - }) - - ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") - recipientKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - keychain := e2e.Env.NewKeychain(1) - keychain.Add(recipientKey) - nodeURI := e2e.Env.GetRandomNodeURI() - baseWallet := e2e.NewWallet(keychain, nodeURI) - xWallet := baseWallet.X() - cWallet := baseWallet.C() - pWallet := baseWallet.P() - - ginkgo.By("defining common configuration") - recipientEthAddress := evm.GetEthAddress(recipientKey) - avaxAssetID := xWallet.AVAXAssetID() - // Use the same owner for sending to X-Chain and importing funds to P-Chain - recipientOwner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - recipientKey.Address(), - }, - } - // Use the same outputs for both X-Chain and C-Chain exports - exportOutputs := []*avax.TransferableOutput{ - { - Asset: avax.Asset{ - ID: avaxAssetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: transferAmount, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - keychain.Keys[0].Address(), - }, - }, - }, - }, - } - - ginkgo.By("adding new node and waiting for it to report healthy") - node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) - e2e.WaitForHealthy(node) - - ginkgo.By("retrieving new node's id and pop") - infoClient := info.NewClient(node.GetProcessContext().URI) - nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) - require.NoError(err) - - ginkgo.By("adding the new node as a validator", func() { - startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) - // Validation duration doesn't actually matter to this - // test - it is only ensuring that adding a validator - // doesn't break interchain transfer. - endTime := startTime.Add(30 * time.Second) - - rewardKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - - const ( - delegationPercent = 0.10 // 10% - delegationShare = reward.PercentDenominator * delegationPercent - ) - - _, err = pWallet.IssueAddPermissionlessValidatorTx( - &txs.SubnetValidator{ - Validator: txs.Validator{ - NodeID: nodeID, - Start: uint64(startTime.Unix()), - End: uint64(endTime.Unix()), - Wght: weight, - }, - Subnet: constants.PrimaryNetworkID, - }, - nodePOP, - pWallet.AVAXAssetID(), - &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{rewardKey.Address()}, - }, - &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{rewardKey.Address()}, - }, - delegationShare, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("adding a delegator to the new node", func() { - startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) - // Delegation duration doesn't actually matter to this - // test - it is only ensuring that adding a delegator - // doesn't break interchain transfer. - endTime := startTime.Add(15 * time.Second) - - rewardKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - - _, err = pWallet.IssueAddPermissionlessDelegatorTx( - &txs.SubnetValidator{ - Validator: txs.Validator{ - NodeID: nodeID, - Start: uint64(startTime.Unix()), - End: uint64(endTime.Unix()), - Wght: weight, - }, - Subnet: constants.PrimaryNetworkID, - }, - pWallet.AVAXAssetID(), - &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{rewardKey.Address()}, - }, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { - _, err := pWallet.IssueExportTx( - xWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { - _, err := xWallet.IssueImportTx( - constants.PlatformChainID, - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { - balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { - _, err := pWallet.IssueExportTx( - cWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("initializing a new eth client") - ethClient := e2e.NewEthClient(nodeURI) - - ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { - _, err := cWallet.IssueImportTx( - constants.PlatformChainID, - recipientEthAddress, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") - balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) - require.NoError(err) - require.Positive(balance.Cmp(big.NewInt(0))) - - ginkgo.By("stopping validator node to free up resources for a bootstrap check") - require.NoError(node.Stop()) - - e2e.CheckBootstrapIsPossible(network) - }) -}) +// import ( +// "math/big" +// "time" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/spf13/cast" + +// "github.com/stretchr/testify/require" + +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/api/info" +// "github.com/ava-labs/avalanchego/config" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/tests/fixture/testnet" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/platformvm/reward" +// "github.com/ava-labs/avalanchego/vms/platformvm/txs" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { +// require := require.New(ginkgo.GinkgoT()) + +// const ( +// transferAmount = 10 * units.Avax +// weight = 2_000 * units.Avax // Used for both validation and delegation +// ) + +// ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { +// network := e2e.Env.GetNetwork() + +// ginkgo.By("checking that the network has a compatible minimum stake duration", func() { +// minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) +// require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) +// }) + +// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") +// recipientKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) +// keychain := e2e.Env.NewKeychain(1) +// keychain.Add(recipientKey) +// nodeURI := e2e.Env.GetRandomNodeURI() +// baseWallet := e2e.NewWallet(keychain, nodeURI) +// xWallet := baseWallet.X() +// cWallet := baseWallet.C() +// pWallet := baseWallet.P() + +// ginkgo.By("defining common configuration") +// recipientEthAddress := evm.GetEthAddress(recipientKey) +// avaxAssetID := xWallet.AVAXAssetID() +// // Use the same owner for sending to X-Chain and importing funds to P-Chain +// recipientOwner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// recipientKey.Address(), +// }, +// } +// // Use the same outputs for both X-Chain and C-Chain exports +// exportOutputs := []*avax.TransferableOutput{ +// { +// Asset: avax.Asset{ +// ID: avaxAssetID, +// }, +// Out: &secp256k1fx.TransferOutput{ +// Amt: transferAmount, +// OutputOwners: secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// keychain.Keys[0].Address(), +// }, +// }, +// }, +// }, +// } + +// ginkgo.By("adding new node and waiting for it to report healthy") +// node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) +// e2e.WaitForHealthy(node) + +// ginkgo.By("retrieving new node's id and pop") +// infoClient := info.NewClient(node.GetProcessContext().URI) +// nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) +// require.NoError(err) + +// ginkgo.By("adding the new node as a validator", func() { +// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) +// // Validation duration doesn't actually matter to this +// // test - it is only ensuring that adding a validator +// // doesn't break interchain transfer. +// endTime := startTime.Add(30 * time.Second) + +// rewardKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) + +// const ( +// delegationPercent = 0.10 // 10% +// delegationShare = reward.PercentDenominator * delegationPercent +// ) + +// _, err = pWallet.IssueAddPermissionlessValidatorTx( +// &txs.SubnetValidator{ +// Validator: txs.Validator{ +// NodeID: nodeID, +// Start: uint64(startTime.Unix()), +// End: uint64(endTime.Unix()), +// Wght: weight, +// }, +// Subnet: constants.PrimaryNetworkID, +// }, +// nodePOP, +// pWallet.AVAXAssetID(), +// &secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{rewardKey.Address()}, +// }, +// &secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{rewardKey.Address()}, +// }, +// delegationShare, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("adding a delegator to the new node", func() { +// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) +// // Delegation duration doesn't actually matter to this +// // test - it is only ensuring that adding a delegator +// // doesn't break interchain transfer. +// endTime := startTime.Add(15 * time.Second) + +// rewardKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) + +// _, err = pWallet.IssueAddPermissionlessDelegatorTx( +// &txs.SubnetValidator{ +// Validator: txs.Validator{ +// NodeID: nodeID, +// Start: uint64(startTime.Unix()), +// End: uint64(endTime.Unix()), +// Wght: weight, +// }, +// Subnet: constants.PrimaryNetworkID, +// }, +// pWallet.AVAXAssetID(), +// &secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{rewardKey.Address()}, +// }, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { +// _, err := pWallet.IssueExportTx( +// xWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { +// _, err := xWallet.IssueImportTx( +// constants.PlatformChainID, +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { +// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { +// _, err := pWallet.IssueExportTx( +// cWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("initializing a new eth client") +// ethClient := e2e.NewEthClient(nodeURI) + +// ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { +// _, err := cWallet.IssueImportTx( +// constants.PlatformChainID, +// recipientEthAddress, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") +// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) +// require.NoError(err) +// require.Positive(balance.Cmp(big.NewInt(0))) + +// ginkgo.By("stopping validator node to free up resources for a bootstrap check") +// require.NoError(node.Stop()) + +// e2e.CheckBootstrapIsPossible(network) +// }) +// }) diff --git a/tests/e2e/x/interchain_workflow.go b/tests/e2e/x/interchain_workflow.go index 373e567a666a..99efca2eced0 100644 --- a/tests/e2e/x/interchain_workflow.go +++ b/tests/e2e/x/interchain_workflow.go @@ -3,151 +3,151 @@ package x -import ( - "math/big" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/tests/e2e" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { - require := require.New(ginkgo.GinkgoT()) - - const transferAmount = 10 * units.Avax - - ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { - nodeURI := e2e.Env.GetRandomNodeURI() - - ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") - recipientKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - keychain := e2e.Env.NewKeychain(1) - keychain.Add(recipientKey) - baseWallet := e2e.NewWallet(keychain, nodeURI) - xWallet := baseWallet.X() - cWallet := baseWallet.C() - pWallet := baseWallet.P() - - ginkgo.By("defining common configuration") - recipientEthAddress := evm.GetEthAddress(recipientKey) - avaxAssetID := xWallet.AVAXAssetID() - // Use the same owner for sending to X-Chain and importing funds to P-Chain - recipientOwner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - recipientKey.Address(), - }, - } - // Use the same outputs for both C-Chain and P-Chain exports - exportOutputs := []*avax.TransferableOutput{ - { - Asset: avax.Asset{ - ID: avaxAssetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: transferAmount, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - keychain.Keys[0].Address(), - }, - }, - }, - }, - } - - ginkgo.By("sending funds from one address to another on the X-Chain", func() { - _, err = xWallet.IssueBaseTx( - []*avax.TransferableOutput{{ - Asset: avax.Asset{ - ID: avaxAssetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: transferAmount, - OutputOwners: recipientOwner, - }, - }}, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { - balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { - _, err := xWallet.IssueExportTx( - cWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("initializing a new eth client") - ethClient := e2e.NewEthClient(nodeURI) - - ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { - _, err := cWallet.IssueImportTx( - xWallet.BlockchainID(), - recipientEthAddress, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") - e2e.Eventually(func() bool { - balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) - require.NoError(err) - return balance.Cmp(big.NewInt(0)) > 0 - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") - - ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { - _, err := xWallet.IssueExportTx( - constants.PlatformChainID, - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { - _, err := pWallet.IssueImportTx( - xWallet.BlockchainID(), - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { - balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) - }) -}) +// import ( +// "math/big" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/stretchr/testify/require" + +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { +// require := require.New(ginkgo.GinkgoT()) + +// const transferAmount = 10 * units.Avax + +// ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { +// nodeURI := e2e.Env.GetRandomNodeURI() + +// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") +// recipientKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) +// keychain := e2e.Env.NewKeychain(1) +// keychain.Add(recipientKey) +// baseWallet := e2e.NewWallet(keychain, nodeURI) +// xWallet := baseWallet.X() +// cWallet := baseWallet.C() +// pWallet := baseWallet.P() + +// ginkgo.By("defining common configuration") +// recipientEthAddress := evm.GetEthAddress(recipientKey) +// avaxAssetID := xWallet.AVAXAssetID() +// // Use the same owner for sending to X-Chain and importing funds to P-Chain +// recipientOwner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// recipientKey.Address(), +// }, +// } +// // Use the same outputs for both C-Chain and P-Chain exports +// exportOutputs := []*avax.TransferableOutput{ +// { +// Asset: avax.Asset{ +// ID: avaxAssetID, +// }, +// Out: &secp256k1fx.TransferOutput{ +// Amt: transferAmount, +// OutputOwners: secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// keychain.Keys[0].Address(), +// }, +// }, +// }, +// }, +// } + +// ginkgo.By("sending funds from one address to another on the X-Chain", func() { +// _, err = xWallet.IssueBaseTx( +// []*avax.TransferableOutput{{ +// Asset: avax.Asset{ +// ID: avaxAssetID, +// }, +// Out: &secp256k1fx.TransferOutput{ +// Amt: transferAmount, +// OutputOwners: recipientOwner, +// }, +// }}, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { +// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { +// _, err := xWallet.IssueExportTx( +// cWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("initializing a new eth client") +// ethClient := e2e.NewEthClient(nodeURI) + +// ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { +// _, err := cWallet.IssueImportTx( +// xWallet.BlockchainID(), +// recipientEthAddress, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") +// e2e.Eventually(func() bool { +// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) +// require.NoError(err) +// return balance.Cmp(big.NewInt(0)) > 0 +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") + +// ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { +// _, err := xWallet.IssueExportTx( +// constants.PlatformChainID, +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { +// _, err := pWallet.IssueImportTx( +// xWallet.BlockchainID(), +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { +// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) +// }) +// }) diff --git a/tests/fixture/testnet/config.go b/tests/fixture/testnet/config.go index 425aa646a690..6c82db1a420f 100644 --- a/tests/fixture/testnet/config.go +++ b/tests/fixture/testnet/config.go @@ -15,10 +15,6 @@ import ( "github.com/spf13/cast" - "github.com/ava-labs/coreth/core" - "github.com/ava-labs/coreth/params" - "github.com/ava-labs/coreth/plugin/evm" - "github.com/ava-labs/avalanchego/config" "github.com/ava-labs/avalanchego/genesis" "github.com/ava-labs/avalanchego/ids" @@ -143,15 +139,15 @@ func (c *NetworkConfig) EnsureGenesis(networkID uint32, validatorIDs []ids.NodeI // Ensure pre-funded keys have arbitrary large balances on both chains to support testing xChainBalances := make(XChainBalanceMap, len(c.FundedKeys)) - cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) - for _, key := range c.FundedKeys { - xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount - cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ - Balance: DefaultFundedKeyCChainAmount, - } - } - - genesis, err := NewTestGenesis(networkID, xChainBalances, cChainBalances, validatorIDs) + // cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) + // for _, key := range c.FundedKeys { + // xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount + // cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ + // Balance: DefaultFundedKeyCChainAmount, + // } + // } + + genesis, err := NewTestGenesis(networkID, xChainBalances /*, cChainBalances*/, validatorIDs) if err != nil { return err } @@ -311,7 +307,7 @@ type XChainBalanceMap map[ids.ShortID]uint64 func NewTestGenesis( networkID uint32, xChainBalances XChainBalanceMap, - cChainBalances core.GenesisAlloc, + // cChainBalances core.GenesisAlloc, validatorIDs []ids.NodeID, ) (*genesis.UnparsedConfig, error) { // Validate inputs @@ -322,7 +318,7 @@ func NewTestGenesis( if len(validatorIDs) == 0 { return nil, errMissingValidatorsForGenesis } - if len(xChainBalances) == 0 || len(cChainBalances) == 0 { + if len(xChainBalances) == 0 /*|| len(cChainBalances) == 0*/ { return nil, errMissingBalancesForGenesis } @@ -394,20 +390,20 @@ func NewTestGenesis( ) } - // Define C-Chain genesis - cChainGenesis := &core.Genesis{ - Config: ¶ms.ChainConfig{ - ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary - }, - Difficulty: big.NewInt(0), // Difficulty is a mandatory field - GasLimit: DefaultGasLimit, - Alloc: cChainBalances, - } - cChainGenesisBytes, err := json.Marshal(cChainGenesis) - if err != nil { - return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) - } - config.CChainGenesis = string(cChainGenesisBytes) + // // Define C-Chain genesis + // cChainGenesis := &core.Genesis{ + // Config: ¶ms.ChainConfig{ + // ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary + // }, + // Difficulty: big.NewInt(0), // Difficulty is a mandatory field + // GasLimit: DefaultGasLimit, + // Alloc: cChainBalances, + // } + // cChainGenesisBytes, err := json.Marshal(cChainGenesis) + // if err != nil { + // return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) + // } + // config.CChainGenesis = string(cChainGenesisBytes) // Give staking rewards for initial validators to a random address. Any testing of staking rewards // will be easier to perform with nodes other than the initial validators since the timing of diff --git a/vms/example/xsvm/cmd/chain/create/cmd.go b/vms/example/xsvm/cmd/chain/create/cmd.go index 1f00491a4ce6..043b4298dcdf 100644 --- a/vms/example/xsvm/cmd/chain/create/cmd.go +++ b/vms/example/xsvm/cmd/chain/create/cmd.go @@ -42,9 +42,9 @@ func createFunc(c *cobra.Command, args []string) error { // that [uri] is hosting. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: config.URI, - AVAXKeychain: kc, - EthKeychain: kc, + URI: config.URI, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(config.SubnetID), }) if err != nil { diff --git a/wallet/chain/c/backend.go b/wallet/chain/c/backend.go index 0a735116b646..b88c8c643bc3 100644 --- a/wallet/chain/c/backend.go +++ b/wallet/chain/c/backend.go @@ -3,153 +3,153 @@ package c -import ( - "errors" - "fmt" - "math/big" - "sync" - - stdcontext "context" - - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/utils/math" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var ( - _ Backend = (*backend)(nil) - - errUnknownTxType = errors.New("unknown tx type") -) - -// Backend defines the full interface required to support a C-chain wallet. -type Backend interface { - common.ChainUTXOs - BuilderBackend - SignerBackend - - AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error -} - -type backend struct { - Context - common.ChainUTXOs - - accountsLock sync.RWMutex - accounts map[ethcommon.Address]*Account -} - -type Account struct { - Balance *big.Int - Nonce uint64 -} - -func NewBackend( - ctx Context, - utxos common.ChainUTXOs, - accounts map[ethcommon.Address]*Account, -) Backend { - return &backend{ - Context: ctx, - ChainUTXOs: utxos, - accounts: accounts, - } -} - -func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { - switch tx := tx.UnsignedAtomicTx.(type) { - case *evm.UnsignedImportTx: - for _, input := range tx.ImportedInputs { - utxoID := input.InputID() - if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { - return err - } - } - - b.accountsLock.Lock() - defer b.accountsLock.Unlock() - - for _, output := range tx.Outs { - account, ok := b.accounts[output.Address] - if !ok { - continue - } - - balance := new(big.Int).SetUint64(output.Amount) - balance.Mul(balance, avaxConversionRate) - account.Balance.Add(account.Balance, balance) - } - case *evm.UnsignedExportTx: - txID := tx.ID() - for i, out := range tx.ExportedOutputs { - err := b.AddUTXO( - ctx, - tx.DestinationChain, - &avax.UTXO{ - UTXOID: avax.UTXOID{ - TxID: txID, - OutputIndex: uint32(i), - }, - Asset: avax.Asset{ID: out.AssetID()}, - Out: out.Out, - }, - ) - if err != nil { - return err - } - } - - b.accountsLock.Lock() - defer b.accountsLock.Unlock() - - for _, input := range tx.Ins { - account, ok := b.accounts[input.Address] - if !ok { - continue - } - - balance := new(big.Int).SetUint64(input.Amount) - balance.Mul(balance, avaxConversionRate) - if account.Balance.Cmp(balance) == -1 { - return errInsufficientFunds - } - account.Balance.Sub(account.Balance, balance) - - newNonce, err := math.Add64(input.Nonce, 1) - if err != nil { - return err - } - account.Nonce = newNonce - } - default: - return fmt.Errorf("%w: %T", errUnknownTxType, tx) - } - return nil -} - -func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { - b.accountsLock.RLock() - defer b.accountsLock.RUnlock() - - account, exists := b.accounts[addr] - if !exists { - return nil, database.ErrNotFound - } - return account.Balance, nil -} - -func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { - b.accountsLock.RLock() - defer b.accountsLock.RUnlock() - - account, exists := b.accounts[addr] - if !exists { - return 0, database.ErrNotFound - } - return account.Nonce, nil -} +// import ( +// "errors" +// "fmt" +// "math/big" +// "sync" + +// stdcontext "context" + +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/database" +// "github.com/ava-labs/avalanchego/utils/math" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var ( +// _ Backend = (*backend)(nil) + +// errUnknownTxType = errors.New("unknown tx type") +// ) + +// // Backend defines the full interface required to support a C-chain wallet. +// type Backend interface { +// common.ChainUTXOs +// BuilderBackend +// SignerBackend + +// AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error +// } + +// type backend struct { +// Context +// common.ChainUTXOs + +// accountsLock sync.RWMutex +// accounts map[ethcommon.Address]*Account +// } + +// type Account struct { +// Balance *big.Int +// Nonce uint64 +// } + +// func NewBackend( +// ctx Context, +// utxos common.ChainUTXOs, +// accounts map[ethcommon.Address]*Account, +// ) Backend { +// return &backend{ +// Context: ctx, +// ChainUTXOs: utxos, +// accounts: accounts, +// } +// } + +// func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { +// switch tx := tx.UnsignedAtomicTx.(type) { +// case *evm.UnsignedImportTx: +// for _, input := range tx.ImportedInputs { +// utxoID := input.InputID() +// if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { +// return err +// } +// } + +// b.accountsLock.Lock() +// defer b.accountsLock.Unlock() + +// for _, output := range tx.Outs { +// account, ok := b.accounts[output.Address] +// if !ok { +// continue +// } + +// balance := new(big.Int).SetUint64(output.Amount) +// balance.Mul(balance, avaxConversionRate) +// account.Balance.Add(account.Balance, balance) +// } +// case *evm.UnsignedExportTx: +// txID := tx.ID() +// for i, out := range tx.ExportedOutputs { +// err := b.AddUTXO( +// ctx, +// tx.DestinationChain, +// &avax.UTXO{ +// UTXOID: avax.UTXOID{ +// TxID: txID, +// OutputIndex: uint32(i), +// }, +// Asset: avax.Asset{ID: out.AssetID()}, +// Out: out.Out, +// }, +// ) +// if err != nil { +// return err +// } +// } + +// b.accountsLock.Lock() +// defer b.accountsLock.Unlock() + +// for _, input := range tx.Ins { +// account, ok := b.accounts[input.Address] +// if !ok { +// continue +// } + +// balance := new(big.Int).SetUint64(input.Amount) +// balance.Mul(balance, avaxConversionRate) +// if account.Balance.Cmp(balance) == -1 { +// return errInsufficientFunds +// } +// account.Balance.Sub(account.Balance, balance) + +// newNonce, err := math.Add64(input.Nonce, 1) +// if err != nil { +// return err +// } +// account.Nonce = newNonce +// } +// default: +// return fmt.Errorf("%w: %T", errUnknownTxType, tx) +// } +// return nil +// } + +// func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { +// b.accountsLock.RLock() +// defer b.accountsLock.RUnlock() + +// account, exists := b.accounts[addr] +// if !exists { +// return nil, database.ErrNotFound +// } +// return account.Balance, nil +// } + +// func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { +// b.accountsLock.RLock() +// defer b.accountsLock.RUnlock() + +// account, exists := b.accounts[addr] +// if !exists { +// return 0, database.ErrNotFound +// } +// return account.Nonce, nil +// } diff --git a/wallet/chain/c/builder.go b/wallet/chain/c/builder.go index d2d088e88a53..c51d2647777e 100644 --- a/wallet/chain/c/builder.go +++ b/wallet/chain/c/builder.go @@ -3,399 +3,399 @@ package c -import ( - "errors" - "math/big" - - stdcontext "context" - - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils" - "github.com/ava-labs/avalanchego/utils/math" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -const avaxConversionRateInt = 1_000_000_000 - -var ( - _ Builder = (*builder)(nil) - - errInsufficientFunds = errors.New("insufficient funds") - - // avaxConversionRate is the conversion rate between the smallest - // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest - // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. - // - // This is only required for AVAX because the denomination of 1 AVAX is 9 - // decimal places on the X and P chains, but is 18 decimal places within the - // EVM. - avaxConversionRate = big.NewInt(avaxConversionRateInt) -) - -// Builder provides a convenient interface for building unsigned C-chain -// transactions. -type Builder interface { - // GetBalance calculates the amount of AVAX that this builder has control - // over. - GetBalance( - options ...common.Option, - ) (*big.Int, error) - - // GetImportableBalance calculates the amount of AVAX that this builder - // could import from the provided chain. - // - // - [chainID] specifies the chain the funds are from. - GetImportableBalance( - chainID ids.ID, - options ...common.Option, - ) (uint64, error) - - // NewImportTx creates an import transaction that attempts to consume all - // the available UTXOs and import the funds to [to]. - // - // - [chainID] specifies the chain to be importing funds from. - // - [to] specifies where to send the imported funds to. - // - [baseFee] specifies the fee price willing to be paid by this tx. - NewImportTx( - chainID ids.ID, - to ethcommon.Address, - baseFee *big.Int, - options ...common.Option, - ) (*evm.UnsignedImportTx, error) - - // NewExportTx creates an export transaction that attempts to send all the - // provided [outputs] to the requested [chainID]. - // - // - [chainID] specifies the chain to be exporting the funds to. - // - [outputs] specifies the outputs to send to the [chainID]. - // - [baseFee] specifies the fee price willing to be paid by this tx. - NewExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - baseFee *big.Int, - options ...common.Option, - ) (*evm.UnsignedExportTx, error) -} - -// BuilderBackend specifies the required information needed to build unsigned -// C-chain transactions. -type BuilderBackend interface { - Context - - UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) - Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) - Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) -} - -type builder struct { - avaxAddrs set.Set[ids.ShortID] - ethAddrs set.Set[ethcommon.Address] - backend BuilderBackend -} - -// NewBuilder returns a new transaction builder. -// -// - [avaxAddrs] is the set of addresses in the AVAX format that the builder -// assumes can be used when signing the transactions in the future. -// - [ethAddrs] is the set of addresses in the Eth format that the builder -// assumes can be used when signing the transactions in the future. -// - [backend] provides the required access to the chain's context and state -// to build out the transactions. -func NewBuilder( - avaxAddrs set.Set[ids.ShortID], - ethAddrs set.Set[ethcommon.Address], - backend BuilderBackend, -) Builder { - return &builder{ - avaxAddrs: avaxAddrs, - ethAddrs: ethAddrs, - backend: backend, - } -} - -func (b *builder) GetBalance( - options ...common.Option, -) (*big.Int, error) { - var ( - ops = common.NewOptions(options) - ctx = ops.Context() - addrs = ops.EthAddresses(b.ethAddrs) - totalBalance = new(big.Int) - ) - for addr := range addrs { - balance, err := b.backend.Balance(ctx, addr) - if err != nil { - return nil, err - } - totalBalance.Add(totalBalance, balance) - } - - return totalBalance, nil -} - -func (b *builder) GetImportableBalance( - chainID ids.ID, - options ...common.Option, -) (uint64, error) { - ops := common.NewOptions(options) - utxos, err := b.backend.UTXOs(ops.Context(), chainID) - if err != nil { - return 0, err - } - - var ( - addrs = ops.Addresses(b.avaxAddrs) - minIssuanceTime = ops.MinIssuanceTime() - avaxAssetID = b.backend.AVAXAssetID() - balance uint64 - ) - for _, utxo := range utxos { - amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) - if !ok { - continue - } - - newBalance, err := math.Add64(balance, amount) - if err != nil { - return 0, err - } - balance = newBalance - } - - return balance, nil -} - -func (b *builder) NewImportTx( - chainID ids.ID, - to ethcommon.Address, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedImportTx, error) { - ops := common.NewOptions(options) - utxos, err := b.backend.UTXOs(ops.Context(), chainID) - if err != nil { - return nil, err - } - - var ( - addrs = ops.Addresses(b.avaxAddrs) - minIssuanceTime = ops.MinIssuanceTime() - avaxAssetID = b.backend.AVAXAssetID() - - importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) - importedAmount uint64 - ) - for _, utxo := range utxos { - amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) - if !ok { - continue - } - - importedInputs = append(importedInputs, &avax.TransferableInput{ - UTXOID: utxo.UTXOID, - Asset: utxo.Asset, - In: &secp256k1fx.TransferInput{ - Amt: amount, - Input: secp256k1fx.Input{ - SigIndices: inputSigIndices, - }, - }, - }) - - newImportedAmount, err := math.Add64(importedAmount, amount) - if err != nil { - return nil, err - } - importedAmount = newImportedAmount - } - - utils.Sort(importedInputs) - tx := &evm.UnsignedImportTx{ - NetworkID: b.backend.NetworkID(), - BlockchainID: b.backend.BlockchainID(), - SourceChain: chainID, - ImportedInputs: importedInputs, - } - - // We must initialize the bytes of the tx to calculate the initial cost - wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} - if err := wrappedTx.Sign(evm.Codec, nil); err != nil { - return nil, err - } - - gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) - if err != nil { - return nil, err - } - gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas - - txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) - if err != nil { - return nil, err - } - - if importedAmount <= txFee { - return nil, errInsufficientFunds - } - - tx.Outs = []evm.EVMOutput{{ - Address: to, - Amount: importedAmount - txFee, - AssetID: avaxAssetID, - }} - return tx, nil -} - -func (b *builder) NewExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedExportTx, error) { - var ( - avaxAssetID = b.backend.AVAXAssetID() - exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) - exportedAmount uint64 - ) - for i, output := range outputs { - exportedOutputs[i] = &avax.TransferableOutput{ - Asset: avax.Asset{ID: avaxAssetID}, - Out: output, - } - - newExportedAmount, err := math.Add64(exportedAmount, output.Amt) - if err != nil { - return nil, err - } - exportedAmount = newExportedAmount - } - - avax.SortTransferableOutputs(exportedOutputs, evm.Codec) - tx := &evm.UnsignedExportTx{ - NetworkID: b.backend.NetworkID(), - BlockchainID: b.backend.BlockchainID(), - DestinationChain: chainID, - ExportedOutputs: exportedOutputs, - } - - // We must initialize the bytes of the tx to calculate the initial cost - wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} - if err := wrappedTx.Sign(evm.Codec, nil); err != nil { - return nil, err - } - - cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) - if err != nil { - return nil, err - } - - initialFee, err := evm.CalculateDynamicFee(cost, baseFee) - if err != nil { - return nil, err - } - - amountToConsume, err := math.Add64(exportedAmount, initialFee) - if err != nil { - return nil, err - } - - var ( - ops = common.NewOptions(options) - ctx = ops.Context() - addrs = ops.EthAddresses(b.ethAddrs) - inputs = make([]evm.EVMInput, 0, addrs.Len()) - ) - for addr := range addrs { - if amountToConsume == 0 { - break - } - - prevFee, err := evm.CalculateDynamicFee(cost, baseFee) - if err != nil { - return nil, err - } - - newCost := cost + evm.EVMInputGas - newFee, err := evm.CalculateDynamicFee(newCost, baseFee) - if err != nil { - return nil, err - } - - additionalFee := newFee - prevFee - - balance, err := b.backend.Balance(ctx, addr) - if err != nil { - return nil, err - } - - // Since the asset is AVAX, we divide by the avaxConversionRate to - // convert back to the correct denomination of AVAX that can be - // exported. - avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() - - // If the balance for [addr] is insufficient to cover the additional - // cost of adding an input to the transaction, skip adding the input - // altogether. - if avaxBalance <= additionalFee { - continue - } - - // Update the cost for the next iteration - cost = newCost - - amountToConsume, err = math.Add64(amountToConsume, additionalFee) - if err != nil { - return nil, err - } - - nonce, err := b.backend.Nonce(ctx, addr) - if err != nil { - return nil, err - } - - inputAmount := math.Min(amountToConsume, avaxBalance) - inputs = append(inputs, evm.EVMInput{ - Address: addr, - Amount: inputAmount, - AssetID: avaxAssetID, - Nonce: nonce, - }) - amountToConsume -= inputAmount - } - - if amountToConsume > 0 { - return nil, errInsufficientFunds - } - - utils.Sort(inputs) - tx.Ins = inputs - return tx, nil -} - -func getSpendableAmount( - utxo *avax.UTXO, - addrs set.Set[ids.ShortID], - minIssuanceTime uint64, - avaxAssetID ids.ID, -) (uint64, []uint32, bool) { - if utxo.Asset.ID != avaxAssetID { - // Only AVAX can be imported - return 0, nil, false - } - - out, ok := utxo.Out.(*secp256k1fx.TransferOutput) - if !ok { - // Can't import an unknown transfer output type - return 0, nil, false - } - - inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) - return out.Amt, inputSigIndices, ok -} +// import ( +// "errors" +// "math/big" + +// stdcontext "context" + +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils" +// "github.com/ava-labs/avalanchego/utils/math" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// const avaxConversionRateInt = 1_000_000_000 + +// var ( +// _ Builder = (*builder)(nil) + +// errInsufficientFunds = errors.New("insufficient funds") + +// // avaxConversionRate is the conversion rate between the smallest +// // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest +// // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. +// // +// // This is only required for AVAX because the denomination of 1 AVAX is 9 +// // decimal places on the X and P chains, but is 18 decimal places within the +// // EVM. +// avaxConversionRate = big.NewInt(avaxConversionRateInt) +// ) + +// // Builder provides a convenient interface for building unsigned C-chain +// // transactions. +// type Builder interface { +// // GetBalance calculates the amount of AVAX that this builder has control +// // over. +// GetBalance( +// options ...common.Option, +// ) (*big.Int, error) + +// // GetImportableBalance calculates the amount of AVAX that this builder +// // could import from the provided chain. +// // +// // - [chainID] specifies the chain the funds are from. +// GetImportableBalance( +// chainID ids.ID, +// options ...common.Option, +// ) (uint64, error) + +// // NewImportTx creates an import transaction that attempts to consume all +// // the available UTXOs and import the funds to [to]. +// // +// // - [chainID] specifies the chain to be importing funds from. +// // - [to] specifies where to send the imported funds to. +// // - [baseFee] specifies the fee price willing to be paid by this tx. +// NewImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedImportTx, error) + +// // NewExportTx creates an export transaction that attempts to send all the +// // provided [outputs] to the requested [chainID]. +// // +// // - [chainID] specifies the chain to be exporting the funds to. +// // - [outputs] specifies the outputs to send to the [chainID]. +// // - [baseFee] specifies the fee price willing to be paid by this tx. +// NewExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedExportTx, error) +// } + +// // BuilderBackend specifies the required information needed to build unsigned +// // C-chain transactions. +// type BuilderBackend interface { +// Context + +// UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) +// Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) +// Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) +// } + +// type builder struct { +// avaxAddrs set.Set[ids.ShortID] +// ethAddrs set.Set[ethcommon.Address] +// backend BuilderBackend +// } + +// // NewBuilder returns a new transaction builder. +// // +// // - [avaxAddrs] is the set of addresses in the AVAX format that the builder +// // assumes can be used when signing the transactions in the future. +// // - [ethAddrs] is the set of addresses in the Eth format that the builder +// // assumes can be used when signing the transactions in the future. +// // - [backend] provides the required access to the chain's context and state +// // to build out the transactions. +// func NewBuilder( +// avaxAddrs set.Set[ids.ShortID], +// ethAddrs set.Set[ethcommon.Address], +// backend BuilderBackend, +// ) Builder { +// return &builder{ +// avaxAddrs: avaxAddrs, +// ethAddrs: ethAddrs, +// backend: backend, +// } +// } + +// func (b *builder) GetBalance( +// options ...common.Option, +// ) (*big.Int, error) { +// var ( +// ops = common.NewOptions(options) +// ctx = ops.Context() +// addrs = ops.EthAddresses(b.ethAddrs) +// totalBalance = new(big.Int) +// ) +// for addr := range addrs { +// balance, err := b.backend.Balance(ctx, addr) +// if err != nil { +// return nil, err +// } +// totalBalance.Add(totalBalance, balance) +// } + +// return totalBalance, nil +// } + +// func (b *builder) GetImportableBalance( +// chainID ids.ID, +// options ...common.Option, +// ) (uint64, error) { +// ops := common.NewOptions(options) +// utxos, err := b.backend.UTXOs(ops.Context(), chainID) +// if err != nil { +// return 0, err +// } + +// var ( +// addrs = ops.Addresses(b.avaxAddrs) +// minIssuanceTime = ops.MinIssuanceTime() +// avaxAssetID = b.backend.AVAXAssetID() +// balance uint64 +// ) +// for _, utxo := range utxos { +// amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) +// if !ok { +// continue +// } + +// newBalance, err := math.Add64(balance, amount) +// if err != nil { +// return 0, err +// } +// balance = newBalance +// } + +// return balance, nil +// } + +// func (b *builder) NewImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedImportTx, error) { +// ops := common.NewOptions(options) +// utxos, err := b.backend.UTXOs(ops.Context(), chainID) +// if err != nil { +// return nil, err +// } + +// var ( +// addrs = ops.Addresses(b.avaxAddrs) +// minIssuanceTime = ops.MinIssuanceTime() +// avaxAssetID = b.backend.AVAXAssetID() + +// importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) +// importedAmount uint64 +// ) +// for _, utxo := range utxos { +// amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) +// if !ok { +// continue +// } + +// importedInputs = append(importedInputs, &avax.TransferableInput{ +// UTXOID: utxo.UTXOID, +// Asset: utxo.Asset, +// In: &secp256k1fx.TransferInput{ +// Amt: amount, +// Input: secp256k1fx.Input{ +// SigIndices: inputSigIndices, +// }, +// }, +// }) + +// newImportedAmount, err := math.Add64(importedAmount, amount) +// if err != nil { +// return nil, err +// } +// importedAmount = newImportedAmount +// } + +// utils.Sort(importedInputs) +// tx := &evm.UnsignedImportTx{ +// NetworkID: b.backend.NetworkID(), +// BlockchainID: b.backend.BlockchainID(), +// SourceChain: chainID, +// ImportedInputs: importedInputs, +// } + +// // We must initialize the bytes of the tx to calculate the initial cost +// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} +// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { +// return nil, err +// } + +// gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) +// if err != nil { +// return nil, err +// } +// gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas + +// txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) +// if err != nil { +// return nil, err +// } + +// if importedAmount <= txFee { +// return nil, errInsufficientFunds +// } + +// tx.Outs = []evm.EVMOutput{{ +// Address: to, +// Amount: importedAmount - txFee, +// AssetID: avaxAssetID, +// }} +// return tx, nil +// } + +// func (b *builder) NewExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedExportTx, error) { +// var ( +// avaxAssetID = b.backend.AVAXAssetID() +// exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) +// exportedAmount uint64 +// ) +// for i, output := range outputs { +// exportedOutputs[i] = &avax.TransferableOutput{ +// Asset: avax.Asset{ID: avaxAssetID}, +// Out: output, +// } + +// newExportedAmount, err := math.Add64(exportedAmount, output.Amt) +// if err != nil { +// return nil, err +// } +// exportedAmount = newExportedAmount +// } + +// avax.SortTransferableOutputs(exportedOutputs, evm.Codec) +// tx := &evm.UnsignedExportTx{ +// NetworkID: b.backend.NetworkID(), +// BlockchainID: b.backend.BlockchainID(), +// DestinationChain: chainID, +// ExportedOutputs: exportedOutputs, +// } + +// // We must initialize the bytes of the tx to calculate the initial cost +// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} +// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { +// return nil, err +// } + +// cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) +// if err != nil { +// return nil, err +// } + +// initialFee, err := evm.CalculateDynamicFee(cost, baseFee) +// if err != nil { +// return nil, err +// } + +// amountToConsume, err := math.Add64(exportedAmount, initialFee) +// if err != nil { +// return nil, err +// } + +// var ( +// ops = common.NewOptions(options) +// ctx = ops.Context() +// addrs = ops.EthAddresses(b.ethAddrs) +// inputs = make([]evm.EVMInput, 0, addrs.Len()) +// ) +// for addr := range addrs { +// if amountToConsume == 0 { +// break +// } + +// prevFee, err := evm.CalculateDynamicFee(cost, baseFee) +// if err != nil { +// return nil, err +// } + +// newCost := cost + evm.EVMInputGas +// newFee, err := evm.CalculateDynamicFee(newCost, baseFee) +// if err != nil { +// return nil, err +// } + +// additionalFee := newFee - prevFee + +// balance, err := b.backend.Balance(ctx, addr) +// if err != nil { +// return nil, err +// } + +// // Since the asset is AVAX, we divide by the avaxConversionRate to +// // convert back to the correct denomination of AVAX that can be +// // exported. +// avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() + +// // If the balance for [addr] is insufficient to cover the additional +// // cost of adding an input to the transaction, skip adding the input +// // altogether. +// if avaxBalance <= additionalFee { +// continue +// } + +// // Update the cost for the next iteration +// cost = newCost + +// amountToConsume, err = math.Add64(amountToConsume, additionalFee) +// if err != nil { +// return nil, err +// } + +// nonce, err := b.backend.Nonce(ctx, addr) +// if err != nil { +// return nil, err +// } + +// inputAmount := math.Min(amountToConsume, avaxBalance) +// inputs = append(inputs, evm.EVMInput{ +// Address: addr, +// Amount: inputAmount, +// AssetID: avaxAssetID, +// Nonce: nonce, +// }) +// amountToConsume -= inputAmount +// } + +// if amountToConsume > 0 { +// return nil, errInsufficientFunds +// } + +// utils.Sort(inputs) +// tx.Ins = inputs +// return tx, nil +// } + +// func getSpendableAmount( +// utxo *avax.UTXO, +// addrs set.Set[ids.ShortID], +// minIssuanceTime uint64, +// avaxAssetID ids.ID, +// ) (uint64, []uint32, bool) { +// if utxo.Asset.ID != avaxAssetID { +// // Only AVAX can be imported +// return 0, nil, false +// } + +// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) +// if !ok { +// // Can't import an unknown transfer output type +// return 0, nil, false +// } + +// inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) +// return out.Amt, inputSigIndices, ok +// } diff --git a/wallet/chain/c/builder_with_options.go b/wallet/chain/c/builder_with_options.go index 8416dddf9928..9b7ab8399484 100644 --- a/wallet/chain/c/builder_with_options.go +++ b/wallet/chain/c/builder_with_options.go @@ -3,81 +3,81 @@ package c -import ( - "math/big" +// import ( +// "math/big" - "github.com/ava-labs/coreth/plugin/evm" +// "github.com/ava-labs/coreth/plugin/evm" - ethcommon "github.com/ethereum/go-ethereum/common" +// ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) -var _ Builder = (*builderWithOptions)(nil) +// var _ Builder = (*builderWithOptions)(nil) -type builderWithOptions struct { - Builder - options []common.Option -} +// type builderWithOptions struct { +// Builder +// options []common.Option +// } -// NewBuilderWithOptions returns a new transaction builder that will use the -// given options by default. -// -// - [builder] is the builder that will be called to perform the underlying -// operations. -// - [options] will be provided to the builder in addition to the options -// provided in the method calls. -func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { - return &builderWithOptions{ - Builder: builder, - options: options, - } -} +// // NewBuilderWithOptions returns a new transaction builder that will use the +// // given options by default. +// // +// // - [builder] is the builder that will be called to perform the underlying +// // operations. +// // - [options] will be provided to the builder in addition to the options +// // provided in the method calls. +// func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { +// return &builderWithOptions{ +// Builder: builder, +// options: options, +// } +// } -func (b *builderWithOptions) GetBalance( - options ...common.Option, -) (*big.Int, error) { - return b.Builder.GetBalance( - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) GetBalance( +// options ...common.Option, +// ) (*big.Int, error) { +// return b.Builder.GetBalance( +// common.UnionOptions(b.options, options)..., +// ) +// } -func (b *builderWithOptions) GetImportableBalance( - chainID ids.ID, - options ...common.Option, -) (uint64, error) { - return b.Builder.GetImportableBalance( - chainID, - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) GetImportableBalance( +// chainID ids.ID, +// options ...common.Option, +// ) (uint64, error) { +// return b.Builder.GetImportableBalance( +// chainID, +// common.UnionOptions(b.options, options)..., +// ) +// } -func (b *builderWithOptions) NewImportTx( - chainID ids.ID, - to ethcommon.Address, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedImportTx, error) { - return b.Builder.NewImportTx( - chainID, - to, - baseFee, - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) NewImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedImportTx, error) { +// return b.Builder.NewImportTx( +// chainID, +// to, +// baseFee, +// common.UnionOptions(b.options, options)..., +// ) +// } -func (b *builderWithOptions) NewExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedExportTx, error) { - return b.Builder.NewExportTx( - chainID, - outputs, - baseFee, - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) NewExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedExportTx, error) { +// return b.Builder.NewExportTx( +// chainID, +// outputs, +// baseFee, +// common.UnionOptions(b.options, options)..., +// ) +// } diff --git a/wallet/chain/c/context.go b/wallet/chain/c/context.go index d506b42f81fa..1c01d8fb55c8 100644 --- a/wallet/chain/c/context.go +++ b/wallet/chain/c/context.go @@ -3,81 +3,81 @@ package c -import ( - stdcontext "context" +// import ( +// stdcontext "context" - "github.com/ava-labs/avalanchego/api/info" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/avm" -) +// "github.com/ava-labs/avalanchego/api/info" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/avm" +// ) -var _ Context = (*context)(nil) +// var _ Context = (*context)(nil) -type Context interface { - NetworkID() uint32 - BlockchainID() ids.ID - AVAXAssetID() ids.ID -} +// type Context interface { +// NetworkID() uint32 +// BlockchainID() ids.ID +// AVAXAssetID() ids.ID +// } -type context struct { - networkID uint32 - blockchainID ids.ID - avaxAssetID ids.ID -} +// type context struct { +// networkID uint32 +// blockchainID ids.ID +// avaxAssetID ids.ID +// } -func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { - infoClient := info.NewClient(uri) - xChainClient := avm.NewClient(uri, "X") - return NewContextFromClients(ctx, infoClient, xChainClient) -} +// func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { +// infoClient := info.NewClient(uri) +// xChainClient := avm.NewClient(uri, "X") +// return NewContextFromClients(ctx, infoClient, xChainClient) +// } -func NewContextFromClients( - ctx stdcontext.Context, - infoClient info.Client, - xChainClient avm.Client, -) (Context, error) { - networkID, err := infoClient.GetNetworkID(ctx) - if err != nil { - return nil, err - } +// func NewContextFromClients( +// ctx stdcontext.Context, +// infoClient info.Client, +// xChainClient avm.Client, +// ) (Context, error) { +// networkID, err := infoClient.GetNetworkID(ctx) +// if err != nil { +// return nil, err +// } - chainID, err := infoClient.GetBlockchainID(ctx, "C") - if err != nil { - return nil, err - } +// chainID, err := infoClient.GetBlockchainID(ctx, "C") +// if err != nil { +// return nil, err +// } - asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") - if err != nil { - return nil, err - } +// asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") +// if err != nil { +// return nil, err +// } - return NewContext( - networkID, - chainID, - asset.AssetID, - ), nil -} +// return NewContext( +// networkID, +// chainID, +// asset.AssetID, +// ), nil +// } -func NewContext( - networkID uint32, - blockchainID ids.ID, - avaxAssetID ids.ID, -) Context { - return &context{ - networkID: networkID, - blockchainID: blockchainID, - avaxAssetID: avaxAssetID, - } -} +// func NewContext( +// networkID uint32, +// blockchainID ids.ID, +// avaxAssetID ids.ID, +// ) Context { +// return &context{ +// networkID: networkID, +// blockchainID: blockchainID, +// avaxAssetID: avaxAssetID, +// } +// } -func (c *context) NetworkID() uint32 { - return c.networkID -} +// func (c *context) NetworkID() uint32 { +// return c.networkID +// } -func (c *context) BlockchainID() ids.ID { - return c.blockchainID -} +// func (c *context) BlockchainID() ids.ID { +// return c.blockchainID +// } -func (c *context) AVAXAssetID() ids.ID { - return c.avaxAssetID -} +// func (c *context) AVAXAssetID() ids.ID { +// return c.avaxAssetID +// } diff --git a/wallet/chain/c/signer.go b/wallet/chain/c/signer.go index 4fd85ed3b532..4bedc378234b 100644 --- a/wallet/chain/c/signer.go +++ b/wallet/chain/c/signer.go @@ -3,221 +3,221 @@ package c -import ( - "errors" - "fmt" - - stdcontext "context" - - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/crypto/keychain" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/hashing" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/components/verify" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" -) - -const version = 0 - -var ( - _ Signer = (*txSigner)(nil) - - errUnknownInputType = errors.New("unknown input type") - errUnknownCredentialType = errors.New("unknown credential type") - errUnknownOutputType = errors.New("unknown output type") - errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") - - emptySig [secp256k1.SignatureLen]byte -) - -type Signer interface { - SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) - SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error -} - -type EthKeychain interface { - // The returned Signer can provide a signature for [addr] - GetEth(addr ethcommon.Address) (keychain.Signer, bool) - // Returns the set of addresses for which the accessor keeps an associated - // signer - EthAddresses() set.Set[ethcommon.Address] -} - -type SignerBackend interface { - GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) -} - -type txSigner struct { - avaxKC keychain.Keychain - ethKC EthKeychain - backend SignerBackend -} - -func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { - return &txSigner{ - avaxKC: avaxKC, - ethKC: ethKC, - backend: backend, - } -} - -func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { - tx := &evm.Tx{UnsignedAtomicTx: utx} - return tx, s.SignAtomic(ctx, tx) -} - -func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { - switch utx := tx.UnsignedAtomicTx.(type) { - case *evm.UnsignedImportTx: - signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) - if err != nil { - return err - } - return sign(tx, true, signers) - case *evm.UnsignedExportTx: - signers := s.getExportSigners(utx.Ins) - return sign(tx, true, signers) - default: - return fmt.Errorf("%w: %T", errUnknownTxType, tx) - } -} - -func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { - txSigners := make([][]keychain.Signer, len(ins)) - for credIndex, transferInput := range ins { - input, ok := transferInput.In.(*secp256k1fx.TransferInput) - if !ok { - return nil, errUnknownInputType - } - - inputSigners := make([]keychain.Signer, len(input.SigIndices)) - txSigners[credIndex] = inputSigners - - utxoID := transferInput.InputID() - utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) - if err == database.ErrNotFound { - // If we don't have access to the UTXO, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - if err != nil { - return nil, err - } - - out, ok := utxo.Out.(*secp256k1fx.TransferOutput) - if !ok { - return nil, errUnknownOutputType - } - - for sigIndex, addrIndex := range input.SigIndices { - if addrIndex >= uint32(len(out.Addrs)) { - return nil, errInvalidUTXOSigIndex - } - - addr := out.Addrs[addrIndex] - key, ok := s.avaxKC.Get(addr) - if !ok { - // If we don't have access to the key, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - inputSigners[sigIndex] = key - } - } - return txSigners, nil -} - -func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { - txSigners := make([][]keychain.Signer, len(ins)) - for credIndex, input := range ins { - inputSigners := make([]keychain.Signer, 1) - txSigners[credIndex] = inputSigners - - key, ok := s.ethKC.GetEth(input.Address) - if !ok { - // If we don't have access to the key, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - inputSigners[0] = key - } - return txSigners -} - -// TODO: remove [signHash] after the ledger supports signing all transactions. -func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { - unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) - if err != nil { - return fmt.Errorf("couldn't marshal unsigned tx: %w", err) - } - unsignedHash := hashing.ComputeHash256(unsignedBytes) - - if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { - tx.Creds = make([]verify.Verifiable, expectedLen) - } - - sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) - for credIndex, inputSigners := range txSigners { - credIntf := tx.Creds[credIndex] - if credIntf == nil { - credIntf = &secp256k1fx.Credential{} - tx.Creds[credIndex] = credIntf - } - - cred, ok := credIntf.(*secp256k1fx.Credential) - if !ok { - return errUnknownCredentialType - } - if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { - cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) - } - - for sigIndex, signer := range inputSigners { - if signer == nil { - // If we don't have access to the key, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - addr := signer.Address() - if sig := cred.Sigs[sigIndex]; sig != emptySig { - // If this signature has already been populated, we can just - // copy the needed signature for the future. - sigCache[addr] = sig - continue - } - - if sig, exists := sigCache[addr]; exists { - // If this key has already produced a signature, we can just - // copy the previous signature. - cred.Sigs[sigIndex] = sig - continue - } - - var sig []byte - if signHash { - sig, err = signer.SignHash(unsignedHash) - } else { - sig, err = signer.Sign(unsignedBytes) - } - if err != nil { - return fmt.Errorf("problem signing tx: %w", err) - } - copy(cred.Sigs[sigIndex][:], sig) - sigCache[addr] = cred.Sigs[sigIndex] - } - } - - signedBytes, err := evm.Codec.Marshal(version, tx) - if err != nil { - return fmt.Errorf("couldn't marshal tx: %w", err) - } - tx.Initialize(unsignedBytes, signedBytes) - return nil -} +// import ( +// "errors" +// "fmt" + +// stdcontext "context" + +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/database" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils/crypto/keychain" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/hashing" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/components/verify" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// ) + +// const version = 0 + +// var ( +// _ Signer = (*txSigner)(nil) + +// errUnknownInputType = errors.New("unknown input type") +// errUnknownCredentialType = errors.New("unknown credential type") +// errUnknownOutputType = errors.New("unknown output type") +// errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") + +// emptySig [secp256k1.SignatureLen]byte +// ) + +// type Signer interface { +// SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) +// SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error +// } + +// type EthKeychain interface { +// // The returned Signer can provide a signature for [addr] +// GetEth(addr ethcommon.Address) (keychain.Signer, bool) +// // Returns the set of addresses for which the accessor keeps an associated +// // signer +// EthAddresses() set.Set[ethcommon.Address] +// } + +// type SignerBackend interface { +// GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) +// } + +// type txSigner struct { +// avaxKC keychain.Keychain +// ethKC EthKeychain +// backend SignerBackend +// } + +// func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { +// return &txSigner{ +// avaxKC: avaxKC, +// ethKC: ethKC, +// backend: backend, +// } +// } + +// func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { +// tx := &evm.Tx{UnsignedAtomicTx: utx} +// return tx, s.SignAtomic(ctx, tx) +// } + +// func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { +// switch utx := tx.UnsignedAtomicTx.(type) { +// case *evm.UnsignedImportTx: +// signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) +// if err != nil { +// return err +// } +// return sign(tx, true, signers) +// case *evm.UnsignedExportTx: +// signers := s.getExportSigners(utx.Ins) +// return sign(tx, true, signers) +// default: +// return fmt.Errorf("%w: %T", errUnknownTxType, tx) +// } +// } + +// func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { +// txSigners := make([][]keychain.Signer, len(ins)) +// for credIndex, transferInput := range ins { +// input, ok := transferInput.In.(*secp256k1fx.TransferInput) +// if !ok { +// return nil, errUnknownInputType +// } + +// inputSigners := make([]keychain.Signer, len(input.SigIndices)) +// txSigners[credIndex] = inputSigners + +// utxoID := transferInput.InputID() +// utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) +// if err == database.ErrNotFound { +// // If we don't have access to the UTXO, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// if err != nil { +// return nil, err +// } + +// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) +// if !ok { +// return nil, errUnknownOutputType +// } + +// for sigIndex, addrIndex := range input.SigIndices { +// if addrIndex >= uint32(len(out.Addrs)) { +// return nil, errInvalidUTXOSigIndex +// } + +// addr := out.Addrs[addrIndex] +// key, ok := s.avaxKC.Get(addr) +// if !ok { +// // If we don't have access to the key, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// inputSigners[sigIndex] = key +// } +// } +// return txSigners, nil +// } + +// func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { +// txSigners := make([][]keychain.Signer, len(ins)) +// for credIndex, input := range ins { +// inputSigners := make([]keychain.Signer, 1) +// txSigners[credIndex] = inputSigners + +// key, ok := s.ethKC.GetEth(input.Address) +// if !ok { +// // If we don't have access to the key, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// inputSigners[0] = key +// } +// return txSigners +// } + +// // TODO: remove [signHash] after the ledger supports signing all transactions. +// func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { +// unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) +// if err != nil { +// return fmt.Errorf("couldn't marshal unsigned tx: %w", err) +// } +// unsignedHash := hashing.ComputeHash256(unsignedBytes) + +// if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { +// tx.Creds = make([]verify.Verifiable, expectedLen) +// } + +// sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) +// for credIndex, inputSigners := range txSigners { +// credIntf := tx.Creds[credIndex] +// if credIntf == nil { +// credIntf = &secp256k1fx.Credential{} +// tx.Creds[credIndex] = credIntf +// } + +// cred, ok := credIntf.(*secp256k1fx.Credential) +// if !ok { +// return errUnknownCredentialType +// } +// if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { +// cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) +// } + +// for sigIndex, signer := range inputSigners { +// if signer == nil { +// // If we don't have access to the key, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// addr := signer.Address() +// if sig := cred.Sigs[sigIndex]; sig != emptySig { +// // If this signature has already been populated, we can just +// // copy the needed signature for the future. +// sigCache[addr] = sig +// continue +// } + +// if sig, exists := sigCache[addr]; exists { +// // If this key has already produced a signature, we can just +// // copy the previous signature. +// cred.Sigs[sigIndex] = sig +// continue +// } + +// var sig []byte +// if signHash { +// sig, err = signer.SignHash(unsignedHash) +// } else { +// sig, err = signer.Sign(unsignedBytes) +// } +// if err != nil { +// return fmt.Errorf("problem signing tx: %w", err) +// } +// copy(cred.Sigs[sigIndex][:], sig) +// sigCache[addr] = cred.Sigs[sigIndex] +// } +// } + +// signedBytes, err := evm.Codec.Marshal(version, tx) +// if err != nil { +// return fmt.Errorf("couldn't marshal tx: %w", err) +// } +// tx.Initialize(unsignedBytes, signedBytes) +// return nil +// } diff --git a/wallet/chain/c/wallet.go b/wallet/chain/c/wallet.go index fb1a83d53dad..ebee50a9a958 100644 --- a/wallet/chain/c/wallet.go +++ b/wallet/chain/c/wallet.go @@ -3,204 +3,204 @@ package c -import ( - "errors" - "math/big" - "time" - - "github.com/ava-labs/coreth/ethclient" - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var ( - _ Wallet = (*wallet)(nil) - - errNotCommitted = errors.New("not committed") -) - -type Wallet interface { - Context - - // Builder returns the builder that will be used to create the transactions. - Builder() Builder - - // Signer returns the signer that will be used to sign the transactions. - Signer() Signer - - // IssueImportTx creates, signs, and issues an import transaction that - // attempts to consume all the available UTXOs and import the funds to [to]. - // - // - [chainID] specifies the chain to be importing funds from. - // - [to] specifies where to send the imported funds to. - IssueImportTx( - chainID ids.ID, - to ethcommon.Address, - options ...common.Option, - ) (*evm.Tx, error) - - // IssueExportTx creates, signs, and issues an export transaction that - // attempts to send all the provided [outputs] to the requested [chainID]. - // - // - [chainID] specifies the chain to be exporting the funds to. - // - [outputs] specifies the outputs to send to the [chainID]. - IssueExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - options ...common.Option, - ) (*evm.Tx, error) - - // IssueUnsignedTx signs and issues the unsigned tx. - IssueUnsignedAtomicTx( - utx evm.UnsignedAtomicTx, - options ...common.Option, - ) (*evm.Tx, error) - - // IssueAtomicTx issues the signed tx. - IssueAtomicTx( - tx *evm.Tx, - options ...common.Option, - ) error -} - -func NewWallet( - builder Builder, - signer Signer, - avaxClient evm.Client, - ethClient ethclient.Client, - backend Backend, -) Wallet { - return &wallet{ - Backend: backend, - builder: builder, - signer: signer, - avaxClient: avaxClient, - ethClient: ethClient, - } -} - -type wallet struct { - Backend - builder Builder - signer Signer - avaxClient evm.Client - ethClient ethclient.Client -} - -func (w *wallet) Builder() Builder { - return w.builder -} - -func (w *wallet) Signer() Signer { - return w.signer -} - -func (w *wallet) IssueImportTx( - chainID ids.ID, - to ethcommon.Address, - options ...common.Option, -) (*evm.Tx, error) { - baseFee, err := w.baseFee(options) - if err != nil { - return nil, err - } - - utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) - if err != nil { - return nil, err - } - return w.IssueUnsignedAtomicTx(utx, options...) -} - -func (w *wallet) IssueExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - options ...common.Option, -) (*evm.Tx, error) { - baseFee, err := w.baseFee(options) - if err != nil { - return nil, err - } - - utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) - if err != nil { - return nil, err - } - return w.IssueUnsignedAtomicTx(utx, options...) -} - -func (w *wallet) IssueUnsignedAtomicTx( - utx evm.UnsignedAtomicTx, - options ...common.Option, -) (*evm.Tx, error) { - ops := common.NewOptions(options) - ctx := ops.Context() - tx, err := w.signer.SignUnsignedAtomic(ctx, utx) - if err != nil { - return nil, err - } - - return tx, w.IssueAtomicTx(tx, options...) -} - -func (w *wallet) IssueAtomicTx( - tx *evm.Tx, - options ...common.Option, -) error { - ops := common.NewOptions(options) - ctx := ops.Context() - txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) - if err != nil { - return err - } - - if f := ops.PostIssuanceFunc(); f != nil { - f(txID) - } - - if ops.AssumeDecided() { - return w.Backend.AcceptAtomicTx(ctx, tx) - } - - pollFrequency := ops.PollFrequency() - ticker := time.NewTicker(pollFrequency) - defer ticker.Stop() - - for { - status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) - if err != nil { - return err - } - - switch status { - case evm.Accepted: - return w.Backend.AcceptAtomicTx(ctx, tx) - case evm.Dropped, evm.Unknown: - return errNotCommitted - } - - // The tx is Processing. - - select { - case <-ticker.C: - case <-ctx.Done(): - return ctx.Err() - } - } -} - -func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { - ops := common.NewOptions(options) - baseFee := ops.BaseFee(nil) - if baseFee != nil { - return baseFee, nil - } - - ctx := ops.Context() - return w.ethClient.EstimateBaseFee(ctx) -} +// import ( +// "errors" +// "math/big" +// "time" + +// "github.com/ava-labs/coreth/ethclient" +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var ( +// _ Wallet = (*wallet)(nil) + +// errNotCommitted = errors.New("not committed") +// ) + +// type Wallet interface { +// Context + +// // Builder returns the builder that will be used to create the transactions. +// Builder() Builder + +// // Signer returns the signer that will be used to sign the transactions. +// Signer() Signer + +// // IssueImportTx creates, signs, and issues an import transaction that +// // attempts to consume all the available UTXOs and import the funds to [to]. +// // +// // - [chainID] specifies the chain to be importing funds from. +// // - [to] specifies where to send the imported funds to. +// IssueImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// options ...common.Option, +// ) (*evm.Tx, error) + +// // IssueExportTx creates, signs, and issues an export transaction that +// // attempts to send all the provided [outputs] to the requested [chainID]. +// // +// // - [chainID] specifies the chain to be exporting the funds to. +// // - [outputs] specifies the outputs to send to the [chainID]. +// IssueExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// options ...common.Option, +// ) (*evm.Tx, error) + +// // IssueUnsignedTx signs and issues the unsigned tx. +// IssueUnsignedAtomicTx( +// utx evm.UnsignedAtomicTx, +// options ...common.Option, +// ) (*evm.Tx, error) + +// // IssueAtomicTx issues the signed tx. +// IssueAtomicTx( +// tx *evm.Tx, +// options ...common.Option, +// ) error +// } + +// func NewWallet( +// builder Builder, +// signer Signer, +// avaxClient evm.Client, +// ethClient ethclient.Client, +// backend Backend, +// ) Wallet { +// return &wallet{ +// Backend: backend, +// builder: builder, +// signer: signer, +// avaxClient: avaxClient, +// ethClient: ethClient, +// } +// } + +// type wallet struct { +// Backend +// builder Builder +// signer Signer +// avaxClient evm.Client +// ethClient ethclient.Client +// } + +// func (w *wallet) Builder() Builder { +// return w.builder +// } + +// func (w *wallet) Signer() Signer { +// return w.signer +// } + +// func (w *wallet) IssueImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// options ...common.Option, +// ) (*evm.Tx, error) { +// baseFee, err := w.baseFee(options) +// if err != nil { +// return nil, err +// } + +// utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) +// if err != nil { +// return nil, err +// } +// return w.IssueUnsignedAtomicTx(utx, options...) +// } + +// func (w *wallet) IssueExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// options ...common.Option, +// ) (*evm.Tx, error) { +// baseFee, err := w.baseFee(options) +// if err != nil { +// return nil, err +// } + +// utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) +// if err != nil { +// return nil, err +// } +// return w.IssueUnsignedAtomicTx(utx, options...) +// } + +// func (w *wallet) IssueUnsignedAtomicTx( +// utx evm.UnsignedAtomicTx, +// options ...common.Option, +// ) (*evm.Tx, error) { +// ops := common.NewOptions(options) +// ctx := ops.Context() +// tx, err := w.signer.SignUnsignedAtomic(ctx, utx) +// if err != nil { +// return nil, err +// } + +// return tx, w.IssueAtomicTx(tx, options...) +// } + +// func (w *wallet) IssueAtomicTx( +// tx *evm.Tx, +// options ...common.Option, +// ) error { +// ops := common.NewOptions(options) +// ctx := ops.Context() +// txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) +// if err != nil { +// return err +// } + +// if f := ops.PostIssuanceFunc(); f != nil { +// f(txID) +// } + +// if ops.AssumeDecided() { +// return w.Backend.AcceptAtomicTx(ctx, tx) +// } + +// pollFrequency := ops.PollFrequency() +// ticker := time.NewTicker(pollFrequency) +// defer ticker.Stop() + +// for { +// status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) +// if err != nil { +// return err +// } + +// switch status { +// case evm.Accepted: +// return w.Backend.AcceptAtomicTx(ctx, tx) +// case evm.Dropped, evm.Unknown: +// return errNotCommitted +// } + +// // The tx is Processing. + +// select { +// case <-ticker.C: +// case <-ctx.Done(): +// return ctx.Err() +// } +// } +// } + +// func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { +// ops := common.NewOptions(options) +// baseFee := ops.BaseFee(nil) +// if baseFee != nil { +// return baseFee, nil +// } + +// ctx := ops.Context() +// return w.ethClient.EstimateBaseFee(ctx) +// } diff --git a/wallet/chain/c/wallet_with_options.go b/wallet/chain/c/wallet_with_options.go index 7d6193683d49..fd69a6d4fd02 100644 --- a/wallet/chain/c/wallet_with_options.go +++ b/wallet/chain/c/wallet_with_options.go @@ -3,80 +3,80 @@ package c -import ( - "github.com/ava-labs/coreth/plugin/evm" +// import ( +// "github.com/ava-labs/coreth/plugin/evm" - ethcommon "github.com/ethereum/go-ethereum/common" +// ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) -var _ Wallet = (*walletWithOptions)(nil) +// var _ Wallet = (*walletWithOptions)(nil) -func NewWalletWithOptions( - wallet Wallet, - options ...common.Option, -) Wallet { - return &walletWithOptions{ - Wallet: wallet, - options: options, - } -} +// func NewWalletWithOptions( +// wallet Wallet, +// options ...common.Option, +// ) Wallet { +// return &walletWithOptions{ +// Wallet: wallet, +// options: options, +// } +// } -type walletWithOptions struct { - Wallet - options []common.Option -} +// type walletWithOptions struct { +// Wallet +// options []common.Option +// } -func (w *walletWithOptions) Builder() Builder { - return NewBuilderWithOptions( - w.Wallet.Builder(), - w.options..., - ) -} +// func (w *walletWithOptions) Builder() Builder { +// return NewBuilderWithOptions( +// w.Wallet.Builder(), +// w.options..., +// ) +// } -func (w *walletWithOptions) IssueImportTx( - chainID ids.ID, - to ethcommon.Address, - options ...common.Option, -) (*evm.Tx, error) { - return w.Wallet.IssueImportTx( - chainID, - to, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// options ...common.Option, +// ) (*evm.Tx, error) { +// return w.Wallet.IssueImportTx( +// chainID, +// to, +// common.UnionOptions(w.options, options)..., +// ) +// } -func (w *walletWithOptions) IssueExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - options ...common.Option, -) (*evm.Tx, error) { - return w.Wallet.IssueExportTx( - chainID, - outputs, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// options ...common.Option, +// ) (*evm.Tx, error) { +// return w.Wallet.IssueExportTx( +// chainID, +// outputs, +// common.UnionOptions(w.options, options)..., +// ) +// } -func (w *walletWithOptions) IssueUnsignedAtomicTx( - utx evm.UnsignedAtomicTx, - options ...common.Option, -) (*evm.Tx, error) { - return w.Wallet.IssueUnsignedAtomicTx( - utx, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueUnsignedAtomicTx( +// utx evm.UnsignedAtomicTx, +// options ...common.Option, +// ) (*evm.Tx, error) { +// return w.Wallet.IssueUnsignedAtomicTx( +// utx, +// common.UnionOptions(w.options, options)..., +// ) +// } -func (w *walletWithOptions) IssueAtomicTx( - tx *evm.Tx, - options ...common.Option, -) error { - return w.Wallet.IssueAtomicTx( - tx, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueAtomicTx( +// tx *evm.Tx, +// options ...common.Option, +// ) error { +// return w.Wallet.IssueAtomicTx( +// tx, +// common.UnionOptions(w.options, options)..., +// ) +// } diff --git a/wallet/subnet/primary/api.go b/wallet/subnet/primary/api.go index 3ac72c217884..3260c05a0a1b 100644 --- a/wallet/subnet/primary/api.go +++ b/wallet/subnet/primary/api.go @@ -5,12 +5,6 @@ package primary import ( "context" - "fmt" - - "github.com/ava-labs/coreth/ethclient" - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ethereum/go-ethereum/common" "github.com/ava-labs/avalanchego/api/info" "github.com/ava-labs/avalanchego/codec" @@ -22,7 +16,6 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm" "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" ) @@ -59,9 +52,9 @@ type AVAXState struct { PCTX p.Context XClient avm.Client XCTX x.Context - CClient evm.Client - CCTX c.Context - UTXOs UTXOs + // CClient evm.Client + // CCTX c.Context + UTXOs UTXOs } func FetchState( @@ -75,7 +68,7 @@ func FetchState( infoClient := info.NewClient(uri) pClient := platformvm.NewClient(uri) xClient := avm.NewClient(uri, "X") - cClient := evm.NewCChainClient(uri) + // cClient := evm.NewCChainClient(uri) pCTX, err := p.NewContextFromClients(ctx, infoClient, xClient) if err != nil { @@ -87,10 +80,10 @@ func FetchState( return nil, err } - cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) - if err != nil { - return nil, err - } + // cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) + // if err != nil { + // return nil, err + // } utxos := NewUTXOs() addrList := addrs.List() @@ -109,11 +102,11 @@ func FetchState( client: xClient, codec: x.Parser.Codec(), }, - { - id: cCTX.BlockchainID(), - client: cClient, - codec: evm.Codec, - }, + // { + // id: cCTX.BlockchainID(), + // client: cClient, + // codec: evm.Codec, + // }, } for _, destinationChain := range chains { for _, sourceChain := range chains { @@ -136,52 +129,52 @@ func FetchState( PCTX: pCTX, XClient: xClient, XCTX: xCTX, - CClient: cClient, - CCTX: cCTX, - UTXOs: utxos, + // CClient: cClient, + // CCTX: cCTX, + UTXOs: utxos, }, nil } -type EthState struct { - Client ethclient.Client - Accounts map[common.Address]*c.Account -} - -func FetchEthState( - ctx context.Context, - uri string, - addrs set.Set[common.Address], -) (*EthState, error) { - path := fmt.Sprintf( - "%s/ext/%s/C/rpc", - uri, - constants.ChainAliasPrefix, - ) - client, err := ethclient.Dial(path) - if err != nil { - return nil, err - } - - accounts := make(map[common.Address]*c.Account, addrs.Len()) - for addr := range addrs { - balance, err := client.BalanceAt(ctx, addr, nil) - if err != nil { - return nil, err - } - nonce, err := client.NonceAt(ctx, addr, nil) - if err != nil { - return nil, err - } - accounts[addr] = &c.Account{ - Balance: balance, - Nonce: nonce, - } - } - return &EthState{ - Client: client, - Accounts: accounts, - }, nil -} +// type EthState struct { +// Client ethclient.Client +// Accounts map[common.Address]*c.Account +// } + +// func FetchEthState( +// ctx context.Context, +// uri string, +// addrs set.Set[common.Address], +// ) (*EthState, error) { +// path := fmt.Sprintf( +// "%s/ext/%s/C/rpc", +// uri, +// constants.ChainAliasPrefix, +// ) +// client, err := ethclient.Dial(path) +// if err != nil { +// return nil, err +// } + +// accounts := make(map[common.Address]*c.Account, addrs.Len()) +// for addr := range addrs { +// balance, err := client.BalanceAt(ctx, addr, nil) +// if err != nil { +// return nil, err +// } +// nonce, err := client.NonceAt(ctx, addr, nil) +// if err != nil { +// return nil, err +// } +// accounts[addr] = &c.Account{ +// Balance: balance, +// Nonce: nonce, +// } +// } +// return &EthState{ +// Client: client, +// Accounts: accounts, +// }, nil +// } // AddAllUTXOs fetches all the UTXOs referenced by [addresses] that were sent // from [sourceChainID] to [destinationChainID] from the [client]. It then uses diff --git a/wallet/subnet/primary/example_test.go b/wallet/subnet/primary/example_test.go index 483c049d4ac0..4a73e8c070b2 100644 --- a/wallet/subnet/primary/example_test.go +++ b/wallet/subnet/primary/example_test.go @@ -30,7 +30,7 @@ func ExampleWallet() { wallet, err := MakeWallet(ctx, &WalletConfig{ URI: LocalAPIURI, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet with: %s\n", err) diff --git a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go index d5e8ce422307..21c081d2982b 100644 --- a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go @@ -46,9 +46,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/add-primary-validator/main.go b/wallet/subnet/primary/examples/add-primary-validator/main.go index a56dae23db3a..13c28f995f63 100644 --- a/wallet/subnet/primary/examples/add-primary-validator/main.go +++ b/wallet/subnet/primary/examples/add-primary-validator/main.go @@ -45,7 +45,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/c-chain-export/main.go b/wallet/subnet/primary/examples/c-chain-export/main.go index fec55c899feb..a6b9a0c810b8 100644 --- a/wallet/subnet/primary/examples/c-chain-export/main.go +++ b/wallet/subnet/primary/examples/c-chain-export/main.go @@ -3,70 +3,70 @@ package main -import ( - "context" - "log" - "time" +// import ( +// "context" +// "log" +// "time" - "github.com/ava-labs/avalanchego/genesis" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary" -) +// "github.com/ava-labs/avalanchego/genesis" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary" +// ) -func main() { - key := genesis.EWOQKey - uri := primary.LocalAPIURI - kc := secp256k1fx.NewKeychain(key) - avaxAddr := key.Address() +// func main() { +// key := genesis.EWOQKey +// uri := primary.LocalAPIURI +// kc := secp256k1fx.NewKeychain(key) +// avaxAddr := key.Address() - ctx := context.Background() +// ctx := context.Background() - // MakeWallet fetches the available UTXOs owned by [kc] on the network that - // [uri] is hosting. - walletSyncStartTime := time.Now() - wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, - }) - if err != nil { - log.Fatalf("failed to initialize wallet: %s\n", err) - } - log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) +// // MakeWallet fetches the available UTXOs owned by [kc] on the network that +// // [uri] is hosting. +// walletSyncStartTime := time.Now() +// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ +// URI: uri, +// AVAXKeychain: kc, +// EthKeychain: kc, +// }) +// if err != nil { +// log.Fatalf("failed to initialize wallet: %s\n", err) +// } +// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) - // Get the P-chain wallet - pWallet := wallet.P() - cWallet := wallet.C() +// // Get the P-chain wallet +// pWallet := wallet.P() +// cWallet := wallet.C() - // Pull out useful constants to use when issuing transactions. - cChainID := cWallet.BlockchainID() - owner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - avaxAddr, - }, - } +// // Pull out useful constants to use when issuing transactions. +// cChainID := cWallet.BlockchainID() +// owner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// avaxAddr, +// }, +// } - exportStartTime := time.Now() - exportTx, err := cWallet.IssueExportTx( - constants.PlatformChainID, - []*secp256k1fx.TransferOutput{{ - Amt: units.Avax, - OutputOwners: owner, - }}, - ) - if err != nil { - log.Fatalf("failed to issue export transaction: %s\n", err) - } - log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) +// exportStartTime := time.Now() +// exportTx, err := cWallet.IssueExportTx( +// constants.PlatformChainID, +// []*secp256k1fx.TransferOutput{{ +// Amt: units.Avax, +// OutputOwners: owner, +// }}, +// ) +// if err != nil { +// log.Fatalf("failed to issue export transaction: %s\n", err) +// } +// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) - importStartTime := time.Now() - importTx, err := pWallet.IssueImportTx(cChainID, &owner) - if err != nil { - log.Fatalf("failed to issue import transaction: %s\n", err) - } - log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) -} +// importStartTime := time.Now() +// importTx, err := pWallet.IssueImportTx(cChainID, &owner) +// if err != nil { +// log.Fatalf("failed to issue import transaction: %s\n", err) +// } +// log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) +// } diff --git a/wallet/subnet/primary/examples/c-chain-import/main.go b/wallet/subnet/primary/examples/c-chain-import/main.go index b4dc4e603eb3..2d9b8a244cb0 100644 --- a/wallet/subnet/primary/examples/c-chain-import/main.go +++ b/wallet/subnet/primary/examples/c-chain-import/main.go @@ -3,75 +3,75 @@ package main -import ( - "context" - "log" - "time" +// import ( +// "context" +// "log" +// "time" - "github.com/ava-labs/coreth/plugin/evm" +// "github.com/ava-labs/coreth/plugin/evm" - "github.com/ava-labs/avalanchego/genesis" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary" -) +// "github.com/ava-labs/avalanchego/genesis" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary" +// ) -func main() { - key := genesis.EWOQKey - uri := primary.LocalAPIURI - kc := secp256k1fx.NewKeychain(key) - avaxAddr := key.Address() - ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) +// func main() { +// key := genesis.EWOQKey +// uri := primary.LocalAPIURI +// kc := secp256k1fx.NewKeychain(key) +// avaxAddr := key.Address() +// ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) - ctx := context.Background() +// ctx := context.Background() - // MakeWallet fetches the available UTXOs owned by [kc] on the network that - // [uri] is hosting. - walletSyncStartTime := time.Now() - wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, - }) - if err != nil { - log.Fatalf("failed to initialize wallet: %s\n", err) - } - log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) +// // MakeWallet fetches the available UTXOs owned by [kc] on the network that +// // [uri] is hosting. +// walletSyncStartTime := time.Now() +// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ +// URI: uri, +// AVAXKeychain: kc, +// EthKeychain: kc, +// }) +// if err != nil { +// log.Fatalf("failed to initialize wallet: %s\n", err) +// } +// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) - // Get the P-chain wallet - pWallet := wallet.P() - cWallet := wallet.C() +// // Get the P-chain wallet +// pWallet := wallet.P() +// cWallet := wallet.C() - // Pull out useful constants to use when issuing transactions. - cChainID := cWallet.BlockchainID() - avaxAssetID := cWallet.AVAXAssetID() - owner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - avaxAddr, - }, - } +// // Pull out useful constants to use when issuing transactions. +// cChainID := cWallet.BlockchainID() +// avaxAssetID := cWallet.AVAXAssetID() +// owner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// avaxAddr, +// }, +// } - exportStartTime := time.Now() - exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ - Asset: avax.Asset{ID: avaxAssetID}, - Out: &secp256k1fx.TransferOutput{ - Amt: units.Avax, - OutputOwners: owner, - }, - }}) - if err != nil { - log.Fatalf("failed to issue export transaction: %s\n", err) - } - log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) +// exportStartTime := time.Now() +// exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ +// Asset: avax.Asset{ID: avaxAssetID}, +// Out: &secp256k1fx.TransferOutput{ +// Amt: units.Avax, +// OutputOwners: owner, +// }, +// }}) +// if err != nil { +// log.Fatalf("failed to issue export transaction: %s\n", err) +// } +// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) - importStartTime := time.Now() - importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) - if err != nil { - log.Fatalf("failed to issue import transaction: %s\n", err) - } - log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) -} +// importStartTime := time.Now() +// importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) +// if err != nil { +// log.Fatalf("failed to issue import transaction: %s\n", err) +// } +// log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) +// } diff --git a/wallet/subnet/primary/examples/create-asset/main.go b/wallet/subnet/primary/examples/create-asset/main.go index 30804f083df6..0bccfbb5fc52 100644 --- a/wallet/subnet/primary/examples/create-asset/main.go +++ b/wallet/subnet/primary/examples/create-asset/main.go @@ -30,7 +30,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-chain/main.go b/wallet/subnet/primary/examples/create-chain/main.go index 5e6898a1b649..521a3cca53cf 100644 --- a/wallet/subnet/primary/examples/create-chain/main.go +++ b/wallet/subnet/primary/examples/create-chain/main.go @@ -41,9 +41,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/create-locked-stakeable/main.go b/wallet/subnet/primary/examples/create-locked-stakeable/main.go index e688968e9e8a..92f1b5cb0e1b 100644 --- a/wallet/subnet/primary/examples/create-locked-stakeable/main.go +++ b/wallet/subnet/primary/examples/create-locked-stakeable/main.go @@ -39,7 +39,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-subnet/main.go b/wallet/subnet/primary/examples/create-subnet/main.go index add98ea7931c..3e8d69bc016a 100644 --- a/wallet/subnet/primary/examples/create-subnet/main.go +++ b/wallet/subnet/primary/examples/create-subnet/main.go @@ -28,7 +28,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/remove-subnet-validator/main.go b/wallet/subnet/primary/examples/remove-subnet-validator/main.go index 2842c7c0a790..46f4b85124db 100644 --- a/wallet/subnet/primary/examples/remove-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/remove-subnet-validator/main.go @@ -38,9 +38,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/wallet.go b/wallet/subnet/primary/wallet.go index 54de390d029c..de50d12f866b 100644 --- a/wallet/subnet/primary/wallet.go +++ b/wallet/subnet/primary/wallet.go @@ -11,7 +11,6 @@ import ( "github.com/ava-labs/avalanchego/utils/crypto/keychain" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" @@ -23,13 +22,13 @@ var _ Wallet = (*wallet)(nil) type Wallet interface { P() p.Wallet X() x.Wallet - C() c.Wallet + // C() c.Wallet } type wallet struct { p p.Wallet x x.Wallet - c c.Wallet + // c c.Wallet } func (w *wallet) P() p.Wallet { @@ -40,16 +39,16 @@ func (w *wallet) X() x.Wallet { return w.x } -func (w *wallet) C() c.Wallet { - return w.c -} +// func (w *wallet) C() c.Wallet { +// return w.c +// } // Creates a new default wallet -func NewWallet(p p.Wallet, x x.Wallet, c c.Wallet) Wallet { +func NewWallet(p p.Wallet, x x.Wallet /*, c c.Wallet*/) Wallet { return &wallet{ p: p, x: x, - c: c, + // c: c, } } @@ -58,7 +57,7 @@ func NewWalletWithOptions(w Wallet, options ...common.Option) Wallet { return NewWallet( p.NewWalletWithOptions(w.P(), options...), x.NewWalletWithOptions(w.X(), options...), - c.NewWalletWithOptions(w.C(), options...), + // c.NewWalletWithOptions(w.C(), options...), ) } @@ -67,7 +66,7 @@ type WalletConfig struct { URI string // required // Keys to use for signing all transactions. AVAXKeychain keychain.Keychain // required - EthKeychain c.EthKeychain // required + // EthKeychain c.EthKeychain // required // Set of P-chain transactions that the wallet should know about to be able // to generate transactions. PChainTxs map[ids.ID]*txs.Tx // optional @@ -93,11 +92,11 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { return nil, err } - ethAddrs := config.EthKeychain.EthAddresses() - ethState, err := FetchEthState(ctx, config.URI, ethAddrs) - if err != nil { - return nil, err - } + // ethAddrs := config.EthKeychain.EthAddresses() + // ethState, err := FetchEthState(ctx, config.URI, ethAddrs) + // if err != nil { + // return nil, err + // } pChainTxs := config.PChainTxs if pChainTxs == nil { @@ -127,15 +126,15 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { xBuilder := x.NewBuilder(avaxAddrs, xBackend) xSigner := x.NewSigner(config.AVAXKeychain, xBackend) - cChainID := avaxState.CCTX.BlockchainID() - cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) - cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) - cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) - cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) + // cChainID := avaxState.CCTX.BlockchainID() + // cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) + // cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) + // cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) + // cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) return NewWallet( p.NewWallet(pBuilder, pSigner, avaxState.PClient, pBackend), x.NewWallet(xBuilder, xSigner, avaxState.XClient, xBackend), - c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), + // c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), ), nil } From 55e3adfd353324efa89c4dfd17e33cdc99854280 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 8 Nov 2023 13:12:34 +0100 Subject: [PATCH 32/36] bumped coreth version --- go.mod | 25 + go.sum | 76 ++ node/node.go | 4 +- tests/e2e/c/dynamic_fees.go | 326 +++---- tests/e2e/c/interchain_workflow.go | 320 +++---- tests/e2e/e2e.go | 114 +-- tests/e2e/p/interchain_workflow.go | 444 +++++----- tests/e2e/x/interchain_workflow.go | 296 +++---- tests/fixture/testnet/config.go | 54 +- vms/example/xsvm/cmd/chain/create/cmd.go | 6 +- wallet/chain/c/backend.go | 300 +++---- wallet/chain/c/builder.go | 792 +++++++++--------- wallet/chain/c/builder_with_options.go | 136 +-- wallet/chain/c/context.go | 130 +-- wallet/chain/c/signer.go | 436 +++++----- wallet/chain/c/wallet.go | 402 ++++----- wallet/chain/c/wallet_with_options.go | 134 +-- wallet/subnet/primary/api.go | 119 +-- wallet/subnet/primary/example_test.go | 2 +- .../add-permissioned-subnet-validator/main.go | 6 +- .../examples/add-primary-validator/main.go | 2 +- .../primary/examples/c-chain-export/main.go | 118 +-- .../primary/examples/c-chain-import/main.go | 126 +-- .../primary/examples/create-asset/main.go | 2 +- .../primary/examples/create-chain/main.go | 6 +- .../examples/create-locked-stakeable/main.go | 2 +- .../primary/examples/create-subnet/main.go | 2 +- .../examples/remove-subnet-validator/main.go | 6 +- wallet/subnet/primary/wallet.go | 41 +- 29 files changed, 2274 insertions(+), 2153 deletions(-) diff --git a/go.mod b/go.mod index d88ed76f20e2..a11af14364b2 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/DataDog/zstd v1.5.2 github.com/Microsoft/go-winio v0.5.2 github.com/NYTimes/gziphandler v1.1.1 + github.com/ava-labs/coreth v0.12.8-rc.1.0.20231108120716-bb29d644e8fb github.com/ava-labs/ledger-avalanche/go v0.0.0-20231102202641-ae2ebdaeac34 github.com/btcsuite/btcd/btcutil v1.1.3 github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 @@ -74,6 +75,7 @@ require ( github.com/BurntSushi/toml v1.2.1 // indirect github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/VictoriaMetrics/fastcache v1.10.0 // indirect github.com/benbjohnson/clock v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect @@ -82,26 +84,44 @@ require ( github.com/cockroachdb/errors v1.9.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/redact v1.1.3 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set/v2 v2.1.0 // indirect + github.com/dlclark/regexp2 v1.7.0 // indirect + github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect + github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/frankban/quicktest v1.14.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect + github.com/go-stack/stack v1.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/go-cmp v0.5.9 // indirect + github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 // indirect + github.com/hashicorp/go-bexpr v0.1.10 // indirect + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/klauspost/compress v1.15.15 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/magiconair/properties v1.8.6 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mitchellh/pointerstructure v1.2.0 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect @@ -109,12 +129,17 @@ require ( github.com/prometheus/common v0.39.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sanity-io/litter v1.5.1 // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/status-im/keycard-go v0.2.0 // indirect github.com/subosito/gotenv v1.3.0 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/zondax/hid v0.9.2 // indirect github.com/zondax/ledger-go v0.14.3 // indirect diff --git a/go.sum b/go.sum index fc0e99dd49fb..59e6338d3b61 100644 --- a/go.sum +++ b/go.sum @@ -56,12 +56,18 @@ github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cq github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= +github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY= +github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/ava-labs/coreth v0.12.8-rc.1.0.20231108120716-bb29d644e8fb h1:fF29dpDn1JxkQ+uX8oNiEuEgJ/sLzdrAx9slSY9rIN0= +github.com/ava-labs/coreth v0.12.8-rc.1.0.20231108120716-bb29d644e8fb/go.mod h1:3nYchxy6KE8cPT3pcW3ArwqgGdvR0sowgZbL5IcLz8Q= github.com/ava-labs/ledger-avalanche/go v0.0.0-20231102202641-ae2ebdaeac34 h1:mg9Uw6oZFJKytJxgxnl3uxZOs/SB8CVHg6Io4Tf99Zc= github.com/ava-labs/ledger-avalanche/go v0.0.0-20231102202641-ae2ebdaeac34/go.mod h1:pJxaT9bUgeRNVmNRgtCHb7sFDIRKy7CzTQVi8gGNT6g= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= @@ -98,13 +104,18 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= @@ -136,12 +147,16 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= +github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= @@ -152,6 +167,14 @@ github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6ps github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= +github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= +github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= +github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -168,6 +191,8 @@ github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2 github.com/ethereum/go-ethereum v1.12.0/go.mod h1:/oo2X/dZLJjf2mJ6YT9wcWxa4nNJDBKDBU6sFIpx1Gs= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -176,6 +201,8 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= @@ -199,7 +226,11 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= @@ -284,10 +315,14 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -308,11 +343,17 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 h1:kr3j8iIMR4ywO/O0rvksXaJvauGGCMg2zAZIiNZ9uIQ= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0/go.mod h1:ummNFgdgLhhX7aIiy35vVmQNS0rWXknfPE0qe6fmFXg= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw= +github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e/go.mod h1:j9cQbcqHQujT0oKJ38PylVfqohClLr3CvDC+Qcg+lhU= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8= @@ -324,6 +365,7 @@ github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3 github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -365,6 +407,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -372,6 +415,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= @@ -382,11 +426,17 @@ github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -395,8 +445,11 @@ github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -415,6 +468,8 @@ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -482,6 +537,8 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sanity-io/litter v1.5.1 h1:dwnrSypP6q56o3lFxTU+t2fwQ9A+U5qrXVO4Qg9KwVU= github.com/sanity-io/litter v1.5.1/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0= @@ -517,6 +574,8 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= +github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -548,10 +607,14 @@ github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZF github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= +github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -563,6 +626,8 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1: github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= @@ -572,6 +637,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= @@ -670,6 +736,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -715,6 +782,7 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -738,6 +806,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -802,8 +871,12 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -820,6 +893,7 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -883,6 +957,7 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1007,6 +1082,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= diff --git a/node/node.go b/node/node.go index 67d6e63f8bb2..d4763db746ec 100644 --- a/node/node.go +++ b/node/node.go @@ -25,7 +25,7 @@ import ( "go.uber.org/zap" - // coreth "github.com/ava-labs/coreth/plugin/evm" + coreth "github.com/ava-labs/coreth/plugin/evm" "github.com/ava-labs/avalanchego/api/admin" "github.com/ava-labs/avalanchego/api/auth" @@ -945,7 +945,7 @@ func (n *Node) initVMs() error { CreateAssetTxFee: n.Config.CreateAssetTxFee, }, }), - // vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), + vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), n.VMManager.RegisterFactory(context.TODO(), secp256k1fx.ID, &secp256k1fx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), nftfx.ID, &nftfx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), propertyfx.ID, &propertyfx.Factory{}), diff --git a/tests/e2e/c/dynamic_fees.go b/tests/e2e/c/dynamic_fees.go index 8748dda7451d..c8e005621983 100644 --- a/tests/e2e/c/dynamic_fees.go +++ b/tests/e2e/c/dynamic_fees.go @@ -3,166 +3,166 @@ package c -// import ( -// "math/big" -// "strings" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/stretchr/testify/require" - -// "github.com/ethereum/go-ethereum/accounts/abi" -// "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/coreth/core/types" -// "github.com/ava-labs/coreth/params" -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/tests" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/tests/fixture/testnet" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// ) - -// // This test uses the compiled bin for `hashing.sol` as -// // well as its ABI contained in `hashing_contract.go`. - -// var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { -// require := require.New(ginkgo.GinkgoT()) - -// // Need a gas limit much larger than the standard 21_000 to enable -// // the contract to induce a gas price increase -// const largeGasLimit = uint64(8_000_000) - -// // TODO(marun) What is the significance of this value? -// gasTip := big.NewInt(1000 * params.GWei) - -// ginkgo.It("should ensure that the gas price is affected by load", func() { -// ginkgo.By("creating a new private network to ensure isolation from other tests") -// privateNetwork := e2e.Env.NewPrivateNetwork() - -// ginkgo.By("allocating a pre-funded key") -// key := privateNetwork.GetConfig().FundedKeys[0] -// ethAddress := evm.GetEthAddress(key) - -// ginkgo.By("initializing a coreth client") -// node := privateNetwork.GetNodes()[0] -// nodeURI := testnet.NodeURI{ -// NodeID: node.GetID(), -// URI: node.GetProcessContext().URI, -// } -// ethClient := e2e.NewEthClient(nodeURI) - -// ginkgo.By("initializing a transaction signer") -// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) -// require.NoError(err) -// signer := types.NewEIP155Signer(cChainID) -// ecdsaKey := key.ToECDSA() -// sign := func(tx *types.Transaction) *types.Transaction { -// signedTx, err := types.SignTx(tx, signer, ecdsaKey) -// require.NoError(err) -// return signedTx -// } - -// var contractAddress common.Address -// ginkgo.By("deploying an expensive contract", func() { -// // Create transaction -// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) -// require.NoError(err) -// compiledContract := common.Hex2Bytes(hashingCompiledContract) -// tx := types.NewTx(&types.LegacyTx{ -// Nonce: nonce, -// GasPrice: gasTip, -// Gas: largeGasLimit, -// Value: common.Big0, -// Data: compiledContract, -// }) - -// // Send the transaction and wait for acceptance -// signedTx := sign(tx) -// receipt := e2e.SendEthTransaction(ethClient, signedTx) - -// contractAddress = receipt.ContractAddress -// }) - -// var gasPrice *big.Int -// ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { -// // Evaluate the bytes representation of the contract -// hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) -// require.NoError(err) -// contractData, err := hashingABI.Pack("hashIt") -// require.NoError(err) - -// var initialGasPrice *big.Int -// e2e.Eventually(func() bool { -// // Check the gas price -// var err error -// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) -// require.NoError(err) -// if initialGasPrice == nil { -// initialGasPrice = gasPrice -// tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) -// } else if gasPrice.Cmp(initialGasPrice) > 0 { -// // Gas price has increased -// tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) -// return true -// } - -// // Create the transaction -// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) -// require.NoError(err) -// tx := types.NewTx(&types.LegacyTx{ -// Nonce: nonce, -// GasPrice: gasTip, -// Gas: largeGasLimit, -// To: &contractAddress, -// Value: common.Big0, -// Data: contractData, -// }) - -// // Send the transaction and wait for acceptance -// signedTx := sign(tx) -// _ = e2e.SendEthTransaction(ethClient, signedTx) - -// // The gas price will be checked at the start of the next iteration -// return false -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") -// }) - -// ginkgo.By("waiting for the gas price to decrease...", func() { -// initialGasPrice := gasPrice -// e2e.Eventually(func() bool { -// var err error -// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) -// require.NoError(err) -// tests.Outf("{{blue}}.{{/}}") -// return initialGasPrice.Cmp(gasPrice) > 0 -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") -// tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) -// }) - -// ginkgo.By("sending funds at the current gas price", func() { -// // Create a recipient address -// recipientKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) -// recipientEthAddress := evm.GetEthAddress(recipientKey) - -// // Create transaction -// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) -// require.NoError(err) -// tx := types.NewTx(&types.LegacyTx{ -// Nonce: nonce, -// GasPrice: gasPrice, -// Gas: e2e.DefaultGasLimit, -// To: &recipientEthAddress, -// Value: common.Big0, -// }) - -// // Send the transaction and wait for acceptance -// signedTx := sign(tx) -// _ = e2e.SendEthTransaction(ethClient, signedTx) -// }) - -// e2e.CheckBootstrapIsPossible(privateNetwork) -// }) -// }) +import ( + "math/big" + "strings" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/coreth/params" + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/tests" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/tests/fixture/testnet" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +) + +// This test uses the compiled bin for `hashing.sol` as +// well as its ABI contained in `hashing_contract.go`. + +var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { + require := require.New(ginkgo.GinkgoT()) + + // Need a gas limit much larger than the standard 21_000 to enable + // the contract to induce a gas price increase + const largeGasLimit = uint64(8_000_000) + + // TODO(marun) What is the significance of this value? + gasTip := big.NewInt(1000 * params.GWei) + + ginkgo.It("should ensure that the gas price is affected by load", func() { + ginkgo.By("creating a new private network to ensure isolation from other tests") + privateNetwork := e2e.Env.NewPrivateNetwork() + + ginkgo.By("allocating a pre-funded key") + key := privateNetwork.GetConfig().FundedKeys[0] + ethAddress := evm.GetEthAddress(key) + + ginkgo.By("initializing a coreth client") + node := privateNetwork.GetNodes()[0] + nodeURI := testnet.NodeURI{ + NodeID: node.GetID(), + URI: node.GetProcessContext().URI, + } + ethClient := e2e.NewEthClient(nodeURI) + + ginkgo.By("initializing a transaction signer") + cChainID, err := ethClient.ChainID(e2e.DefaultContext()) + require.NoError(err) + signer := types.NewEIP155Signer(cChainID) + ecdsaKey := key.ToECDSA() + sign := func(tx *types.Transaction) *types.Transaction { + signedTx, err := types.SignTx(tx, signer, ecdsaKey) + require.NoError(err) + return signedTx + } + + var contractAddress common.Address + ginkgo.By("deploying an expensive contract", func() { + // Create transaction + nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) + require.NoError(err) + compiledContract := common.Hex2Bytes(hashingCompiledContract) + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + GasPrice: gasTip, + Gas: largeGasLimit, + Value: common.Big0, + Data: compiledContract, + }) + + // Send the transaction and wait for acceptance + signedTx := sign(tx) + receipt := e2e.SendEthTransaction(ethClient, signedTx) + + contractAddress = receipt.ContractAddress + }) + + var gasPrice *big.Int + ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { + // Evaluate the bytes representation of the contract + hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) + require.NoError(err) + contractData, err := hashingABI.Pack("hashIt") + require.NoError(err) + + var initialGasPrice *big.Int + e2e.Eventually(func() bool { + // Check the gas price + var err error + gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) + require.NoError(err) + if initialGasPrice == nil { + initialGasPrice = gasPrice + tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) + } else if gasPrice.Cmp(initialGasPrice) > 0 { + // Gas price has increased + tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) + return true + } + + // Create the transaction + nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) + require.NoError(err) + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + GasPrice: gasTip, + Gas: largeGasLimit, + To: &contractAddress, + Value: common.Big0, + Data: contractData, + }) + + // Send the transaction and wait for acceptance + signedTx := sign(tx) + _ = e2e.SendEthTransaction(ethClient, signedTx) + + // The gas price will be checked at the start of the next iteration + return false + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") + }) + + ginkgo.By("waiting for the gas price to decrease...", func() { + initialGasPrice := gasPrice + e2e.Eventually(func() bool { + var err error + gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) + require.NoError(err) + tests.Outf("{{blue}}.{{/}}") + return initialGasPrice.Cmp(gasPrice) > 0 + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") + tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) + }) + + ginkgo.By("sending funds at the current gas price", func() { + // Create a recipient address + recipientKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + recipientEthAddress := evm.GetEthAddress(recipientKey) + + // Create transaction + nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) + require.NoError(err) + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + GasPrice: gasPrice, + Gas: e2e.DefaultGasLimit, + To: &recipientEthAddress, + Value: common.Big0, + }) + + // Send the transaction and wait for acceptance + signedTx := sign(tx) + _ = e2e.SendEthTransaction(ethClient, signedTx) + }) + + e2e.CheckBootstrapIsPossible(privateNetwork) + }) +}) diff --git a/tests/e2e/c/interchain_workflow.go b/tests/e2e/c/interchain_workflow.go index 8c019078ec6c..d4881255ddff 100644 --- a/tests/e2e/c/interchain_workflow.go +++ b/tests/e2e/c/interchain_workflow.go @@ -3,163 +3,163 @@ package c -// import ( -// "math/big" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/stretchr/testify/require" - -// "github.com/ava-labs/coreth/core/types" -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { -// require := require.New(ginkgo.GinkgoT()) - -// const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer - -// ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { -// ginkgo.By("initializing a new eth client") -// // Select a random node URI to use for both the eth client and -// // the wallet to avoid having to verify that all nodes are at -// // the same height before initializing the wallet. -// nodeURI := e2e.Env.GetRandomNodeURI() -// ethClient := e2e.NewEthClient(nodeURI) - -// ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") -// senderKey := e2e.Env.AllocateFundedKey() -// senderEthAddress := evm.GetEthAddress(senderKey) -// recipientKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) -// recipientEthAddress := evm.GetEthAddress(recipientKey) - -// ginkgo.By("sending funds from one address to another on the C-Chain", func() { -// // Create transaction -// acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) -// require.NoError(err) -// gasPrice := e2e.SuggestGasPrice(ethClient) -// tx := types.NewTransaction( -// acceptedNonce, -// recipientEthAddress, -// big.NewInt(int64(txAmount)), -// e2e.DefaultGasLimit, -// gasPrice, -// nil, -// ) - -// // Sign transaction -// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) -// require.NoError(err) -// signer := types.NewEIP155Signer(cChainID) -// signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) -// require.NoError(err) - -// _ = e2e.SendEthTransaction(ethClient, signedTx) - -// ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") -// e2e.Eventually(func() bool { -// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) -// require.NoError(err) -// return balance.Cmp(big.NewInt(0)) > 0 -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") -// }) - -// // Wallet must be initialized after sending funds on the -// // C-Chain with the same node URI to ensure wallet state -// // matches on-chain state. -// ginkgo.By("initializing a keychain and associated wallet") -// keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) -// baseWallet := e2e.NewWallet(keychain, nodeURI) -// xWallet := baseWallet.X() -// cWallet := baseWallet.C() -// pWallet := baseWallet.P() - -// ginkgo.By("defining common configuration") -// avaxAssetID := xWallet.AVAXAssetID() -// // Use the same owner for import funds to X-Chain and P-Chain -// recipientOwner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// recipientKey.Address(), -// }, -// } -// // Use the same outputs for both X-Chain and P-Chain exports -// exportOutputs := []*secp256k1fx.TransferOutput{ -// { -// Amt: txAmount, -// OutputOwners: secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// keychain.Keys[0].Address(), -// }, -// }, -// }, -// } - -// ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { -// _, err := cWallet.IssueExportTx( -// xWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { -// _, err := xWallet.IssueImportTx( -// cWallet.BlockchainID(), -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { -// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { -// _, err := cWallet.IssueExportTx( -// constants.PlatformChainID, -// exportOutputs, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { -// _, err = pWallet.IssueImportTx( -// cWallet.BlockchainID(), -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { -// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) -// }) -// }) +import ( + "math/big" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { + require := require.New(ginkgo.GinkgoT()) + + const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer + + ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { + ginkgo.By("initializing a new eth client") + // Select a random node URI to use for both the eth client and + // the wallet to avoid having to verify that all nodes are at + // the same height before initializing the wallet. + nodeURI := e2e.Env.GetRandomNodeURI() + ethClient := e2e.NewEthClient(nodeURI) + + ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") + senderKey := e2e.Env.AllocateFundedKey() + senderEthAddress := evm.GetEthAddress(senderKey) + recipientKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + recipientEthAddress := evm.GetEthAddress(recipientKey) + + ginkgo.By("sending funds from one address to another on the C-Chain", func() { + // Create transaction + acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) + require.NoError(err) + gasPrice := e2e.SuggestGasPrice(ethClient) + tx := types.NewTransaction( + acceptedNonce, + recipientEthAddress, + big.NewInt(int64(txAmount)), + e2e.DefaultGasLimit, + gasPrice, + nil, + ) + + // Sign transaction + cChainID, err := ethClient.ChainID(e2e.DefaultContext()) + require.NoError(err) + signer := types.NewEIP155Signer(cChainID) + signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) + require.NoError(err) + + _ = e2e.SendEthTransaction(ethClient, signedTx) + + ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") + e2e.Eventually(func() bool { + balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) + require.NoError(err) + return balance.Cmp(big.NewInt(0)) > 0 + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") + }) + + // Wallet must be initialized after sending funds on the + // C-Chain with the same node URI to ensure wallet state + // matches on-chain state. + ginkgo.By("initializing a keychain and associated wallet") + keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) + baseWallet := e2e.NewWallet(keychain, nodeURI) + xWallet := baseWallet.X() + cWallet := baseWallet.C() + pWallet := baseWallet.P() + + ginkgo.By("defining common configuration") + avaxAssetID := xWallet.AVAXAssetID() + // Use the same owner for import funds to X-Chain and P-Chain + recipientOwner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + recipientKey.Address(), + }, + } + // Use the same outputs for both X-Chain and P-Chain exports + exportOutputs := []*secp256k1fx.TransferOutput{ + { + Amt: txAmount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + keychain.Keys[0].Address(), + }, + }, + }, + } + + ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { + _, err := cWallet.IssueExportTx( + xWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { + _, err := xWallet.IssueImportTx( + cWallet.BlockchainID(), + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { + balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { + _, err := cWallet.IssueExportTx( + constants.PlatformChainID, + exportOutputs, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { + _, err = pWallet.IssueImportTx( + cWallet.BlockchainID(), + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { + balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) + }) +}) diff --git a/tests/e2e/e2e.go b/tests/e2e/e2e.go index 33b219ae4061..44c5d911e8dd 100644 --- a/tests/e2e/e2e.go +++ b/tests/e2e/e2e.go @@ -7,15 +7,23 @@ package e2e import ( "context" "encoding/json" + "errors" + "fmt" + "math/big" "math/rand" "os" "path/filepath" + "strings" "time" ginkgo "github.com/onsi/ginkgo/v2" "github.com/stretchr/testify/require" + "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/coreth/ethclient" + "github.com/ava-labs/coreth/interfaces" + "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/tests" "github.com/ava-labs/avalanchego/tests/fixture" @@ -139,7 +147,7 @@ func NewWallet(keychain *secp256k1fx.Keychain, nodeURI testnet.NodeURI) primary. baseWallet, err := primary.MakeWallet(DefaultContext(), &primary.WalletConfig{ URI: nodeURI.URI, AVAXKeychain: keychain, - // EthKeychain: keychain, + EthKeychain: keychain, }) require.NoError(ginkgo.GinkgoT(), err) return primary.NewWalletWithOptions( @@ -152,15 +160,15 @@ func NewWallet(keychain *secp256k1fx.Keychain, nodeURI testnet.NodeURI) primary. ) } -// // Create a new eth client targeting the specified node URI. -// func NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { -// tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) -// nodeAddress := strings.Split(nodeURI.URI, "//")[1] -// uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) -// client, err := ethclient.Dial(uri) -// require.NoError(ginkgo.GinkgoT(), err) -// return client -// } +// Create a new eth client targeting the specified node URI. +func NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { + tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) + nodeAddress := strings.Split(nodeURI.URI, "//")[1] + uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) + client, err := ethclient.Dial(uri) + require.NoError(ginkgo.GinkgoT(), err) + return client +} // Helper simplifying use of a timed context by canceling the context on ginkgo teardown. func ContextWithTimeout(duration time.Duration) context.Context { @@ -221,49 +229,49 @@ func WaitForHealthy(node testnet.Node) { require.NoError(ginkgo.GinkgoT(), testnet.WaitForHealthy(DefaultContext(), node)) } -// // Sends an eth transaction, waits for the transaction receipt to be issued -// // and checks that the receipt indicates success. -// func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { -// require := require.New(ginkgo.GinkgoT()) - -// txID := signedTx.Hash() -// tests.Outf(" sending eth transaction with ID: %s\n", txID) - -// require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) - -// // Wait for the receipt -// var receipt *types.Receipt -// Eventually(func() bool { -// var err error -// receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) -// if errors.Is(err, interfaces.NotFound) { -// return false // Transaction is still pending -// } -// require.NoError(err) -// return true -// }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") - -// require.Equal(receipt.Status, types.ReceiptStatusSuccessful) -// return receipt -// } - -// // Determines the suggested gas price for the configured client that will -// // maximize the chances of transaction acceptance. -// func SuggestGasPrice(ethClient ethclient.Client) *big.Int { -// gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) -// require.NoError(ginkgo.GinkgoT(), err) -// // Double the suggested gas price to maximize the chances of -// // acceptance. Maybe this can be revisited pending resolution of -// // https://github.com/ava-labs/coreth/issues/314. -// gasPrice.Add(gasPrice, gasPrice) -// return gasPrice -// } - -// // Helper simplifying use via an option of a gas price appropriate for testing. -// func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { -// baseFee := SuggestGasPrice(ethClient) -// return common.WithBaseFee(baseFee) -// } +// Sends an eth transaction, waits for the transaction receipt to be issued +// and checks that the receipt indicates success. +func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { + require := require.New(ginkgo.GinkgoT()) + + txID := signedTx.Hash() + tests.Outf(" sending eth transaction with ID: %s\n", txID) + + require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) + + // Wait for the receipt + var receipt *types.Receipt + Eventually(func() bool { + var err error + receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) + if errors.Is(err, interfaces.NotFound) { + return false // Transaction is still pending + } + require.NoError(err) + return true + }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") + + require.Equal(receipt.Status, types.ReceiptStatusSuccessful) + return receipt +} + +// Determines the suggested gas price for the configured client that will +// maximize the chances of transaction acceptance. +func SuggestGasPrice(ethClient ethclient.Client) *big.Int { + gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) + require.NoError(ginkgo.GinkgoT(), err) + // Double the suggested gas price to maximize the chances of + // acceptance. Maybe this can be revisited pending resolution of + // https://github.com/ava-labs/coreth/issues/314. + gasPrice.Add(gasPrice, gasPrice) + return gasPrice +} + +// Helper simplifying use via an option of a gas price appropriate for testing. +func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { + baseFee := SuggestGasPrice(ethClient) + return common.WithBaseFee(baseFee) +} // Verify that a new node can bootstrap into the network. func CheckBootstrapIsPossible(network testnet.Network) { diff --git a/tests/e2e/p/interchain_workflow.go b/tests/e2e/p/interchain_workflow.go index 33a8345f919f..9bea416294cb 100644 --- a/tests/e2e/p/interchain_workflow.go +++ b/tests/e2e/p/interchain_workflow.go @@ -3,225 +3,225 @@ package p -// import ( -// "math/big" -// "time" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/spf13/cast" - -// "github.com/stretchr/testify/require" - -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/api/info" -// "github.com/ava-labs/avalanchego/config" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/tests/fixture/testnet" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/platformvm/reward" -// "github.com/ava-labs/avalanchego/vms/platformvm/txs" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { -// require := require.New(ginkgo.GinkgoT()) - -// const ( -// transferAmount = 10 * units.Avax -// weight = 2_000 * units.Avax // Used for both validation and delegation -// ) - -// ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { -// network := e2e.Env.GetNetwork() - -// ginkgo.By("checking that the network has a compatible minimum stake duration", func() { -// minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) -// require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) -// }) - -// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") -// recipientKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) -// keychain := e2e.Env.NewKeychain(1) -// keychain.Add(recipientKey) -// nodeURI := e2e.Env.GetRandomNodeURI() -// baseWallet := e2e.NewWallet(keychain, nodeURI) -// xWallet := baseWallet.X() -// cWallet := baseWallet.C() -// pWallet := baseWallet.P() - -// ginkgo.By("defining common configuration") -// recipientEthAddress := evm.GetEthAddress(recipientKey) -// avaxAssetID := xWallet.AVAXAssetID() -// // Use the same owner for sending to X-Chain and importing funds to P-Chain -// recipientOwner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// recipientKey.Address(), -// }, -// } -// // Use the same outputs for both X-Chain and C-Chain exports -// exportOutputs := []*avax.TransferableOutput{ -// { -// Asset: avax.Asset{ -// ID: avaxAssetID, -// }, -// Out: &secp256k1fx.TransferOutput{ -// Amt: transferAmount, -// OutputOwners: secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// keychain.Keys[0].Address(), -// }, -// }, -// }, -// }, -// } - -// ginkgo.By("adding new node and waiting for it to report healthy") -// node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) -// e2e.WaitForHealthy(node) - -// ginkgo.By("retrieving new node's id and pop") -// infoClient := info.NewClient(node.GetProcessContext().URI) -// nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) -// require.NoError(err) - -// ginkgo.By("adding the new node as a validator", func() { -// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) -// // Validation duration doesn't actually matter to this -// // test - it is only ensuring that adding a validator -// // doesn't break interchain transfer. -// endTime := startTime.Add(30 * time.Second) - -// rewardKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) - -// const ( -// delegationPercent = 0.10 // 10% -// delegationShare = reward.PercentDenominator * delegationPercent -// ) - -// _, err = pWallet.IssueAddPermissionlessValidatorTx( -// &txs.SubnetValidator{ -// Validator: txs.Validator{ -// NodeID: nodeID, -// Start: uint64(startTime.Unix()), -// End: uint64(endTime.Unix()), -// Wght: weight, -// }, -// Subnet: constants.PrimaryNetworkID, -// }, -// nodePOP, -// pWallet.AVAXAssetID(), -// &secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{rewardKey.Address()}, -// }, -// &secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{rewardKey.Address()}, -// }, -// delegationShare, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("adding a delegator to the new node", func() { -// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) -// // Delegation duration doesn't actually matter to this -// // test - it is only ensuring that adding a delegator -// // doesn't break interchain transfer. -// endTime := startTime.Add(15 * time.Second) - -// rewardKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) - -// _, err = pWallet.IssueAddPermissionlessDelegatorTx( -// &txs.SubnetValidator{ -// Validator: txs.Validator{ -// NodeID: nodeID, -// Start: uint64(startTime.Unix()), -// End: uint64(endTime.Unix()), -// Wght: weight, -// }, -// Subnet: constants.PrimaryNetworkID, -// }, -// pWallet.AVAXAssetID(), -// &secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{rewardKey.Address()}, -// }, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { -// _, err := pWallet.IssueExportTx( -// xWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { -// _, err := xWallet.IssueImportTx( -// constants.PlatformChainID, -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { -// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { -// _, err := pWallet.IssueExportTx( -// cWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("initializing a new eth client") -// ethClient := e2e.NewEthClient(nodeURI) - -// ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { -// _, err := cWallet.IssueImportTx( -// constants.PlatformChainID, -// recipientEthAddress, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") -// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) -// require.NoError(err) -// require.Positive(balance.Cmp(big.NewInt(0))) - -// ginkgo.By("stopping validator node to free up resources for a bootstrap check") -// require.NoError(node.Stop()) - -// e2e.CheckBootstrapIsPossible(network) -// }) -// }) +import ( + "math/big" + "time" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/spf13/cast" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/api/info" + "github.com/ava-labs/avalanchego/config" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/tests/fixture/testnet" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/platformvm/reward" + "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { + require := require.New(ginkgo.GinkgoT()) + + const ( + transferAmount = 10 * units.Avax + weight = 2_000 * units.Avax // Used for both validation and delegation + ) + + ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { + network := e2e.Env.GetNetwork() + + ginkgo.By("checking that the network has a compatible minimum stake duration", func() { + minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) + require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) + }) + + ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") + recipientKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + keychain := e2e.Env.NewKeychain(1) + keychain.Add(recipientKey) + nodeURI := e2e.Env.GetRandomNodeURI() + baseWallet := e2e.NewWallet(keychain, nodeURI) + xWallet := baseWallet.X() + cWallet := baseWallet.C() + pWallet := baseWallet.P() + + ginkgo.By("defining common configuration") + recipientEthAddress := evm.GetEthAddress(recipientKey) + avaxAssetID := xWallet.AVAXAssetID() + // Use the same owner for sending to X-Chain and importing funds to P-Chain + recipientOwner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + recipientKey.Address(), + }, + } + // Use the same outputs for both X-Chain and C-Chain exports + exportOutputs := []*avax.TransferableOutput{ + { + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: transferAmount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + keychain.Keys[0].Address(), + }, + }, + }, + }, + } + + ginkgo.By("adding new node and waiting for it to report healthy") + node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) + e2e.WaitForHealthy(node) + + ginkgo.By("retrieving new node's id and pop") + infoClient := info.NewClient(node.GetProcessContext().URI) + nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) + require.NoError(err) + + ginkgo.By("adding the new node as a validator", func() { + startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) + // Validation duration doesn't actually matter to this + // test - it is only ensuring that adding a validator + // doesn't break interchain transfer. + endTime := startTime.Add(30 * time.Second) + + rewardKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + + const ( + delegationPercent = 0.10 // 10% + delegationShare = reward.PercentDenominator * delegationPercent + ) + + _, err = pWallet.IssueAddPermissionlessValidatorTx( + &txs.SubnetValidator{ + Validator: txs.Validator{ + NodeID: nodeID, + Start: uint64(startTime.Unix()), + End: uint64(endTime.Unix()), + Wght: weight, + }, + Subnet: constants.PrimaryNetworkID, + }, + nodePOP, + pWallet.AVAXAssetID(), + &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{rewardKey.Address()}, + }, + &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{rewardKey.Address()}, + }, + delegationShare, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("adding a delegator to the new node", func() { + startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) + // Delegation duration doesn't actually matter to this + // test - it is only ensuring that adding a delegator + // doesn't break interchain transfer. + endTime := startTime.Add(15 * time.Second) + + rewardKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + + _, err = pWallet.IssueAddPermissionlessDelegatorTx( + &txs.SubnetValidator{ + Validator: txs.Validator{ + NodeID: nodeID, + Start: uint64(startTime.Unix()), + End: uint64(endTime.Unix()), + Wght: weight, + }, + Subnet: constants.PrimaryNetworkID, + }, + pWallet.AVAXAssetID(), + &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{rewardKey.Address()}, + }, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { + _, err := pWallet.IssueExportTx( + xWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { + _, err := xWallet.IssueImportTx( + constants.PlatformChainID, + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { + balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { + _, err := pWallet.IssueExportTx( + cWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("initializing a new eth client") + ethClient := e2e.NewEthClient(nodeURI) + + ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { + _, err := cWallet.IssueImportTx( + constants.PlatformChainID, + recipientEthAddress, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") + balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) + require.NoError(err) + require.Positive(balance.Cmp(big.NewInt(0))) + + ginkgo.By("stopping validator node to free up resources for a bootstrap check") + require.NoError(node.Stop()) + + e2e.CheckBootstrapIsPossible(network) + }) +}) diff --git a/tests/e2e/x/interchain_workflow.go b/tests/e2e/x/interchain_workflow.go index 99efca2eced0..373e567a666a 100644 --- a/tests/e2e/x/interchain_workflow.go +++ b/tests/e2e/x/interchain_workflow.go @@ -3,151 +3,151 @@ package x -// import ( -// "math/big" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/stretchr/testify/require" - -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { -// require := require.New(ginkgo.GinkgoT()) - -// const transferAmount = 10 * units.Avax - -// ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { -// nodeURI := e2e.Env.GetRandomNodeURI() - -// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") -// recipientKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) -// keychain := e2e.Env.NewKeychain(1) -// keychain.Add(recipientKey) -// baseWallet := e2e.NewWallet(keychain, nodeURI) -// xWallet := baseWallet.X() -// cWallet := baseWallet.C() -// pWallet := baseWallet.P() - -// ginkgo.By("defining common configuration") -// recipientEthAddress := evm.GetEthAddress(recipientKey) -// avaxAssetID := xWallet.AVAXAssetID() -// // Use the same owner for sending to X-Chain and importing funds to P-Chain -// recipientOwner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// recipientKey.Address(), -// }, -// } -// // Use the same outputs for both C-Chain and P-Chain exports -// exportOutputs := []*avax.TransferableOutput{ -// { -// Asset: avax.Asset{ -// ID: avaxAssetID, -// }, -// Out: &secp256k1fx.TransferOutput{ -// Amt: transferAmount, -// OutputOwners: secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// keychain.Keys[0].Address(), -// }, -// }, -// }, -// }, -// } - -// ginkgo.By("sending funds from one address to another on the X-Chain", func() { -// _, err = xWallet.IssueBaseTx( -// []*avax.TransferableOutput{{ -// Asset: avax.Asset{ -// ID: avaxAssetID, -// }, -// Out: &secp256k1fx.TransferOutput{ -// Amt: transferAmount, -// OutputOwners: recipientOwner, -// }, -// }}, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { -// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { -// _, err := xWallet.IssueExportTx( -// cWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("initializing a new eth client") -// ethClient := e2e.NewEthClient(nodeURI) - -// ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { -// _, err := cWallet.IssueImportTx( -// xWallet.BlockchainID(), -// recipientEthAddress, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") -// e2e.Eventually(func() bool { -// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) -// require.NoError(err) -// return balance.Cmp(big.NewInt(0)) > 0 -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") - -// ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { -// _, err := xWallet.IssueExportTx( -// constants.PlatformChainID, -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { -// _, err := pWallet.IssueImportTx( -// xWallet.BlockchainID(), -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { -// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) -// }) -// }) +import ( + "math/big" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/tests/e2e" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { + require := require.New(ginkgo.GinkgoT()) + + const transferAmount = 10 * units.Avax + + ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { + nodeURI := e2e.Env.GetRandomNodeURI() + + ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") + recipientKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + keychain := e2e.Env.NewKeychain(1) + keychain.Add(recipientKey) + baseWallet := e2e.NewWallet(keychain, nodeURI) + xWallet := baseWallet.X() + cWallet := baseWallet.C() + pWallet := baseWallet.P() + + ginkgo.By("defining common configuration") + recipientEthAddress := evm.GetEthAddress(recipientKey) + avaxAssetID := xWallet.AVAXAssetID() + // Use the same owner for sending to X-Chain and importing funds to P-Chain + recipientOwner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + recipientKey.Address(), + }, + } + // Use the same outputs for both C-Chain and P-Chain exports + exportOutputs := []*avax.TransferableOutput{ + { + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: transferAmount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + keychain.Keys[0].Address(), + }, + }, + }, + }, + } + + ginkgo.By("sending funds from one address to another on the X-Chain", func() { + _, err = xWallet.IssueBaseTx( + []*avax.TransferableOutput{{ + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: transferAmount, + OutputOwners: recipientOwner, + }, + }}, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { + balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { + _, err := xWallet.IssueExportTx( + cWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("initializing a new eth client") + ethClient := e2e.NewEthClient(nodeURI) + + ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { + _, err := cWallet.IssueImportTx( + xWallet.BlockchainID(), + recipientEthAddress, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") + e2e.Eventually(func() bool { + balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) + require.NoError(err) + return balance.Cmp(big.NewInt(0)) > 0 + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") + + ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { + _, err := xWallet.IssueExportTx( + constants.PlatformChainID, + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { + _, err := pWallet.IssueImportTx( + xWallet.BlockchainID(), + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { + balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) + }) +}) diff --git a/tests/fixture/testnet/config.go b/tests/fixture/testnet/config.go index 6c82db1a420f..425aa646a690 100644 --- a/tests/fixture/testnet/config.go +++ b/tests/fixture/testnet/config.go @@ -15,6 +15,10 @@ import ( "github.com/spf13/cast" + "github.com/ava-labs/coreth/core" + "github.com/ava-labs/coreth/params" + "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/avalanchego/config" "github.com/ava-labs/avalanchego/genesis" "github.com/ava-labs/avalanchego/ids" @@ -139,15 +143,15 @@ func (c *NetworkConfig) EnsureGenesis(networkID uint32, validatorIDs []ids.NodeI // Ensure pre-funded keys have arbitrary large balances on both chains to support testing xChainBalances := make(XChainBalanceMap, len(c.FundedKeys)) - // cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) - // for _, key := range c.FundedKeys { - // xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount - // cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ - // Balance: DefaultFundedKeyCChainAmount, - // } - // } - - genesis, err := NewTestGenesis(networkID, xChainBalances /*, cChainBalances*/, validatorIDs) + cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) + for _, key := range c.FundedKeys { + xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount + cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ + Balance: DefaultFundedKeyCChainAmount, + } + } + + genesis, err := NewTestGenesis(networkID, xChainBalances, cChainBalances, validatorIDs) if err != nil { return err } @@ -307,7 +311,7 @@ type XChainBalanceMap map[ids.ShortID]uint64 func NewTestGenesis( networkID uint32, xChainBalances XChainBalanceMap, - // cChainBalances core.GenesisAlloc, + cChainBalances core.GenesisAlloc, validatorIDs []ids.NodeID, ) (*genesis.UnparsedConfig, error) { // Validate inputs @@ -318,7 +322,7 @@ func NewTestGenesis( if len(validatorIDs) == 0 { return nil, errMissingValidatorsForGenesis } - if len(xChainBalances) == 0 /*|| len(cChainBalances) == 0*/ { + if len(xChainBalances) == 0 || len(cChainBalances) == 0 { return nil, errMissingBalancesForGenesis } @@ -390,20 +394,20 @@ func NewTestGenesis( ) } - // // Define C-Chain genesis - // cChainGenesis := &core.Genesis{ - // Config: ¶ms.ChainConfig{ - // ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary - // }, - // Difficulty: big.NewInt(0), // Difficulty is a mandatory field - // GasLimit: DefaultGasLimit, - // Alloc: cChainBalances, - // } - // cChainGenesisBytes, err := json.Marshal(cChainGenesis) - // if err != nil { - // return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) - // } - // config.CChainGenesis = string(cChainGenesisBytes) + // Define C-Chain genesis + cChainGenesis := &core.Genesis{ + Config: ¶ms.ChainConfig{ + ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary + }, + Difficulty: big.NewInt(0), // Difficulty is a mandatory field + GasLimit: DefaultGasLimit, + Alloc: cChainBalances, + } + cChainGenesisBytes, err := json.Marshal(cChainGenesis) + if err != nil { + return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) + } + config.CChainGenesis = string(cChainGenesisBytes) // Give staking rewards for initial validators to a random address. Any testing of staking rewards // will be easier to perform with nodes other than the initial validators since the timing of diff --git a/vms/example/xsvm/cmd/chain/create/cmd.go b/vms/example/xsvm/cmd/chain/create/cmd.go index 043b4298dcdf..1f00491a4ce6 100644 --- a/vms/example/xsvm/cmd/chain/create/cmd.go +++ b/vms/example/xsvm/cmd/chain/create/cmd.go @@ -42,9 +42,9 @@ func createFunc(c *cobra.Command, args []string) error { // that [uri] is hosting. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: config.URI, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: config.URI, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(config.SubnetID), }) if err != nil { diff --git a/wallet/chain/c/backend.go b/wallet/chain/c/backend.go index b88c8c643bc3..0a735116b646 100644 --- a/wallet/chain/c/backend.go +++ b/wallet/chain/c/backend.go @@ -3,153 +3,153 @@ package c -// import ( -// "errors" -// "fmt" -// "math/big" -// "sync" - -// stdcontext "context" - -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/database" -// "github.com/ava-labs/avalanchego/utils/math" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var ( -// _ Backend = (*backend)(nil) - -// errUnknownTxType = errors.New("unknown tx type") -// ) - -// // Backend defines the full interface required to support a C-chain wallet. -// type Backend interface { -// common.ChainUTXOs -// BuilderBackend -// SignerBackend - -// AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error -// } - -// type backend struct { -// Context -// common.ChainUTXOs - -// accountsLock sync.RWMutex -// accounts map[ethcommon.Address]*Account -// } - -// type Account struct { -// Balance *big.Int -// Nonce uint64 -// } - -// func NewBackend( -// ctx Context, -// utxos common.ChainUTXOs, -// accounts map[ethcommon.Address]*Account, -// ) Backend { -// return &backend{ -// Context: ctx, -// ChainUTXOs: utxos, -// accounts: accounts, -// } -// } - -// func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { -// switch tx := tx.UnsignedAtomicTx.(type) { -// case *evm.UnsignedImportTx: -// for _, input := range tx.ImportedInputs { -// utxoID := input.InputID() -// if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { -// return err -// } -// } - -// b.accountsLock.Lock() -// defer b.accountsLock.Unlock() - -// for _, output := range tx.Outs { -// account, ok := b.accounts[output.Address] -// if !ok { -// continue -// } - -// balance := new(big.Int).SetUint64(output.Amount) -// balance.Mul(balance, avaxConversionRate) -// account.Balance.Add(account.Balance, balance) -// } -// case *evm.UnsignedExportTx: -// txID := tx.ID() -// for i, out := range tx.ExportedOutputs { -// err := b.AddUTXO( -// ctx, -// tx.DestinationChain, -// &avax.UTXO{ -// UTXOID: avax.UTXOID{ -// TxID: txID, -// OutputIndex: uint32(i), -// }, -// Asset: avax.Asset{ID: out.AssetID()}, -// Out: out.Out, -// }, -// ) -// if err != nil { -// return err -// } -// } - -// b.accountsLock.Lock() -// defer b.accountsLock.Unlock() - -// for _, input := range tx.Ins { -// account, ok := b.accounts[input.Address] -// if !ok { -// continue -// } - -// balance := new(big.Int).SetUint64(input.Amount) -// balance.Mul(balance, avaxConversionRate) -// if account.Balance.Cmp(balance) == -1 { -// return errInsufficientFunds -// } -// account.Balance.Sub(account.Balance, balance) - -// newNonce, err := math.Add64(input.Nonce, 1) -// if err != nil { -// return err -// } -// account.Nonce = newNonce -// } -// default: -// return fmt.Errorf("%w: %T", errUnknownTxType, tx) -// } -// return nil -// } - -// func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { -// b.accountsLock.RLock() -// defer b.accountsLock.RUnlock() - -// account, exists := b.accounts[addr] -// if !exists { -// return nil, database.ErrNotFound -// } -// return account.Balance, nil -// } - -// func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { -// b.accountsLock.RLock() -// defer b.accountsLock.RUnlock() - -// account, exists := b.accounts[addr] -// if !exists { -// return 0, database.ErrNotFound -// } -// return account.Nonce, nil -// } +import ( + "errors" + "fmt" + "math/big" + "sync" + + stdcontext "context" + + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/utils/math" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var ( + _ Backend = (*backend)(nil) + + errUnknownTxType = errors.New("unknown tx type") +) + +// Backend defines the full interface required to support a C-chain wallet. +type Backend interface { + common.ChainUTXOs + BuilderBackend + SignerBackend + + AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error +} + +type backend struct { + Context + common.ChainUTXOs + + accountsLock sync.RWMutex + accounts map[ethcommon.Address]*Account +} + +type Account struct { + Balance *big.Int + Nonce uint64 +} + +func NewBackend( + ctx Context, + utxos common.ChainUTXOs, + accounts map[ethcommon.Address]*Account, +) Backend { + return &backend{ + Context: ctx, + ChainUTXOs: utxos, + accounts: accounts, + } +} + +func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { + switch tx := tx.UnsignedAtomicTx.(type) { + case *evm.UnsignedImportTx: + for _, input := range tx.ImportedInputs { + utxoID := input.InputID() + if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { + return err + } + } + + b.accountsLock.Lock() + defer b.accountsLock.Unlock() + + for _, output := range tx.Outs { + account, ok := b.accounts[output.Address] + if !ok { + continue + } + + balance := new(big.Int).SetUint64(output.Amount) + balance.Mul(balance, avaxConversionRate) + account.Balance.Add(account.Balance, balance) + } + case *evm.UnsignedExportTx: + txID := tx.ID() + for i, out := range tx.ExportedOutputs { + err := b.AddUTXO( + ctx, + tx.DestinationChain, + &avax.UTXO{ + UTXOID: avax.UTXOID{ + TxID: txID, + OutputIndex: uint32(i), + }, + Asset: avax.Asset{ID: out.AssetID()}, + Out: out.Out, + }, + ) + if err != nil { + return err + } + } + + b.accountsLock.Lock() + defer b.accountsLock.Unlock() + + for _, input := range tx.Ins { + account, ok := b.accounts[input.Address] + if !ok { + continue + } + + balance := new(big.Int).SetUint64(input.Amount) + balance.Mul(balance, avaxConversionRate) + if account.Balance.Cmp(balance) == -1 { + return errInsufficientFunds + } + account.Balance.Sub(account.Balance, balance) + + newNonce, err := math.Add64(input.Nonce, 1) + if err != nil { + return err + } + account.Nonce = newNonce + } + default: + return fmt.Errorf("%w: %T", errUnknownTxType, tx) + } + return nil +} + +func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { + b.accountsLock.RLock() + defer b.accountsLock.RUnlock() + + account, exists := b.accounts[addr] + if !exists { + return nil, database.ErrNotFound + } + return account.Balance, nil +} + +func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { + b.accountsLock.RLock() + defer b.accountsLock.RUnlock() + + account, exists := b.accounts[addr] + if !exists { + return 0, database.ErrNotFound + } + return account.Nonce, nil +} diff --git a/wallet/chain/c/builder.go b/wallet/chain/c/builder.go index c51d2647777e..d2d088e88a53 100644 --- a/wallet/chain/c/builder.go +++ b/wallet/chain/c/builder.go @@ -3,399 +3,399 @@ package c -// import ( -// "errors" -// "math/big" - -// stdcontext "context" - -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils" -// "github.com/ava-labs/avalanchego/utils/math" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// const avaxConversionRateInt = 1_000_000_000 - -// var ( -// _ Builder = (*builder)(nil) - -// errInsufficientFunds = errors.New("insufficient funds") - -// // avaxConversionRate is the conversion rate between the smallest -// // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest -// // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. -// // -// // This is only required for AVAX because the denomination of 1 AVAX is 9 -// // decimal places on the X and P chains, but is 18 decimal places within the -// // EVM. -// avaxConversionRate = big.NewInt(avaxConversionRateInt) -// ) - -// // Builder provides a convenient interface for building unsigned C-chain -// // transactions. -// type Builder interface { -// // GetBalance calculates the amount of AVAX that this builder has control -// // over. -// GetBalance( -// options ...common.Option, -// ) (*big.Int, error) - -// // GetImportableBalance calculates the amount of AVAX that this builder -// // could import from the provided chain. -// // -// // - [chainID] specifies the chain the funds are from. -// GetImportableBalance( -// chainID ids.ID, -// options ...common.Option, -// ) (uint64, error) - -// // NewImportTx creates an import transaction that attempts to consume all -// // the available UTXOs and import the funds to [to]. -// // -// // - [chainID] specifies the chain to be importing funds from. -// // - [to] specifies where to send the imported funds to. -// // - [baseFee] specifies the fee price willing to be paid by this tx. -// NewImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedImportTx, error) - -// // NewExportTx creates an export transaction that attempts to send all the -// // provided [outputs] to the requested [chainID]. -// // -// // - [chainID] specifies the chain to be exporting the funds to. -// // - [outputs] specifies the outputs to send to the [chainID]. -// // - [baseFee] specifies the fee price willing to be paid by this tx. -// NewExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedExportTx, error) -// } - -// // BuilderBackend specifies the required information needed to build unsigned -// // C-chain transactions. -// type BuilderBackend interface { -// Context - -// UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) -// Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) -// Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) -// } - -// type builder struct { -// avaxAddrs set.Set[ids.ShortID] -// ethAddrs set.Set[ethcommon.Address] -// backend BuilderBackend -// } - -// // NewBuilder returns a new transaction builder. -// // -// // - [avaxAddrs] is the set of addresses in the AVAX format that the builder -// // assumes can be used when signing the transactions in the future. -// // - [ethAddrs] is the set of addresses in the Eth format that the builder -// // assumes can be used when signing the transactions in the future. -// // - [backend] provides the required access to the chain's context and state -// // to build out the transactions. -// func NewBuilder( -// avaxAddrs set.Set[ids.ShortID], -// ethAddrs set.Set[ethcommon.Address], -// backend BuilderBackend, -// ) Builder { -// return &builder{ -// avaxAddrs: avaxAddrs, -// ethAddrs: ethAddrs, -// backend: backend, -// } -// } - -// func (b *builder) GetBalance( -// options ...common.Option, -// ) (*big.Int, error) { -// var ( -// ops = common.NewOptions(options) -// ctx = ops.Context() -// addrs = ops.EthAddresses(b.ethAddrs) -// totalBalance = new(big.Int) -// ) -// for addr := range addrs { -// balance, err := b.backend.Balance(ctx, addr) -// if err != nil { -// return nil, err -// } -// totalBalance.Add(totalBalance, balance) -// } - -// return totalBalance, nil -// } - -// func (b *builder) GetImportableBalance( -// chainID ids.ID, -// options ...common.Option, -// ) (uint64, error) { -// ops := common.NewOptions(options) -// utxos, err := b.backend.UTXOs(ops.Context(), chainID) -// if err != nil { -// return 0, err -// } - -// var ( -// addrs = ops.Addresses(b.avaxAddrs) -// minIssuanceTime = ops.MinIssuanceTime() -// avaxAssetID = b.backend.AVAXAssetID() -// balance uint64 -// ) -// for _, utxo := range utxos { -// amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) -// if !ok { -// continue -// } - -// newBalance, err := math.Add64(balance, amount) -// if err != nil { -// return 0, err -// } -// balance = newBalance -// } - -// return balance, nil -// } - -// func (b *builder) NewImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedImportTx, error) { -// ops := common.NewOptions(options) -// utxos, err := b.backend.UTXOs(ops.Context(), chainID) -// if err != nil { -// return nil, err -// } - -// var ( -// addrs = ops.Addresses(b.avaxAddrs) -// minIssuanceTime = ops.MinIssuanceTime() -// avaxAssetID = b.backend.AVAXAssetID() - -// importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) -// importedAmount uint64 -// ) -// for _, utxo := range utxos { -// amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) -// if !ok { -// continue -// } - -// importedInputs = append(importedInputs, &avax.TransferableInput{ -// UTXOID: utxo.UTXOID, -// Asset: utxo.Asset, -// In: &secp256k1fx.TransferInput{ -// Amt: amount, -// Input: secp256k1fx.Input{ -// SigIndices: inputSigIndices, -// }, -// }, -// }) - -// newImportedAmount, err := math.Add64(importedAmount, amount) -// if err != nil { -// return nil, err -// } -// importedAmount = newImportedAmount -// } - -// utils.Sort(importedInputs) -// tx := &evm.UnsignedImportTx{ -// NetworkID: b.backend.NetworkID(), -// BlockchainID: b.backend.BlockchainID(), -// SourceChain: chainID, -// ImportedInputs: importedInputs, -// } - -// // We must initialize the bytes of the tx to calculate the initial cost -// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} -// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { -// return nil, err -// } - -// gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) -// if err != nil { -// return nil, err -// } -// gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas - -// txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) -// if err != nil { -// return nil, err -// } - -// if importedAmount <= txFee { -// return nil, errInsufficientFunds -// } - -// tx.Outs = []evm.EVMOutput{{ -// Address: to, -// Amount: importedAmount - txFee, -// AssetID: avaxAssetID, -// }} -// return tx, nil -// } - -// func (b *builder) NewExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedExportTx, error) { -// var ( -// avaxAssetID = b.backend.AVAXAssetID() -// exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) -// exportedAmount uint64 -// ) -// for i, output := range outputs { -// exportedOutputs[i] = &avax.TransferableOutput{ -// Asset: avax.Asset{ID: avaxAssetID}, -// Out: output, -// } - -// newExportedAmount, err := math.Add64(exportedAmount, output.Amt) -// if err != nil { -// return nil, err -// } -// exportedAmount = newExportedAmount -// } - -// avax.SortTransferableOutputs(exportedOutputs, evm.Codec) -// tx := &evm.UnsignedExportTx{ -// NetworkID: b.backend.NetworkID(), -// BlockchainID: b.backend.BlockchainID(), -// DestinationChain: chainID, -// ExportedOutputs: exportedOutputs, -// } - -// // We must initialize the bytes of the tx to calculate the initial cost -// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} -// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { -// return nil, err -// } - -// cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) -// if err != nil { -// return nil, err -// } - -// initialFee, err := evm.CalculateDynamicFee(cost, baseFee) -// if err != nil { -// return nil, err -// } - -// amountToConsume, err := math.Add64(exportedAmount, initialFee) -// if err != nil { -// return nil, err -// } - -// var ( -// ops = common.NewOptions(options) -// ctx = ops.Context() -// addrs = ops.EthAddresses(b.ethAddrs) -// inputs = make([]evm.EVMInput, 0, addrs.Len()) -// ) -// for addr := range addrs { -// if amountToConsume == 0 { -// break -// } - -// prevFee, err := evm.CalculateDynamicFee(cost, baseFee) -// if err != nil { -// return nil, err -// } - -// newCost := cost + evm.EVMInputGas -// newFee, err := evm.CalculateDynamicFee(newCost, baseFee) -// if err != nil { -// return nil, err -// } - -// additionalFee := newFee - prevFee - -// balance, err := b.backend.Balance(ctx, addr) -// if err != nil { -// return nil, err -// } - -// // Since the asset is AVAX, we divide by the avaxConversionRate to -// // convert back to the correct denomination of AVAX that can be -// // exported. -// avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() - -// // If the balance for [addr] is insufficient to cover the additional -// // cost of adding an input to the transaction, skip adding the input -// // altogether. -// if avaxBalance <= additionalFee { -// continue -// } - -// // Update the cost for the next iteration -// cost = newCost - -// amountToConsume, err = math.Add64(amountToConsume, additionalFee) -// if err != nil { -// return nil, err -// } - -// nonce, err := b.backend.Nonce(ctx, addr) -// if err != nil { -// return nil, err -// } - -// inputAmount := math.Min(amountToConsume, avaxBalance) -// inputs = append(inputs, evm.EVMInput{ -// Address: addr, -// Amount: inputAmount, -// AssetID: avaxAssetID, -// Nonce: nonce, -// }) -// amountToConsume -= inputAmount -// } - -// if amountToConsume > 0 { -// return nil, errInsufficientFunds -// } - -// utils.Sort(inputs) -// tx.Ins = inputs -// return tx, nil -// } - -// func getSpendableAmount( -// utxo *avax.UTXO, -// addrs set.Set[ids.ShortID], -// minIssuanceTime uint64, -// avaxAssetID ids.ID, -// ) (uint64, []uint32, bool) { -// if utxo.Asset.ID != avaxAssetID { -// // Only AVAX can be imported -// return 0, nil, false -// } - -// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) -// if !ok { -// // Can't import an unknown transfer output type -// return 0, nil, false -// } - -// inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) -// return out.Amt, inputSigIndices, ok -// } +import ( + "errors" + "math/big" + + stdcontext "context" + + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils" + "github.com/ava-labs/avalanchego/utils/math" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +const avaxConversionRateInt = 1_000_000_000 + +var ( + _ Builder = (*builder)(nil) + + errInsufficientFunds = errors.New("insufficient funds") + + // avaxConversionRate is the conversion rate between the smallest + // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest + // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. + // + // This is only required for AVAX because the denomination of 1 AVAX is 9 + // decimal places on the X and P chains, but is 18 decimal places within the + // EVM. + avaxConversionRate = big.NewInt(avaxConversionRateInt) +) + +// Builder provides a convenient interface for building unsigned C-chain +// transactions. +type Builder interface { + // GetBalance calculates the amount of AVAX that this builder has control + // over. + GetBalance( + options ...common.Option, + ) (*big.Int, error) + + // GetImportableBalance calculates the amount of AVAX that this builder + // could import from the provided chain. + // + // - [chainID] specifies the chain the funds are from. + GetImportableBalance( + chainID ids.ID, + options ...common.Option, + ) (uint64, error) + + // NewImportTx creates an import transaction that attempts to consume all + // the available UTXOs and import the funds to [to]. + // + // - [chainID] specifies the chain to be importing funds from. + // - [to] specifies where to send the imported funds to. + // - [baseFee] specifies the fee price willing to be paid by this tx. + NewImportTx( + chainID ids.ID, + to ethcommon.Address, + baseFee *big.Int, + options ...common.Option, + ) (*evm.UnsignedImportTx, error) + + // NewExportTx creates an export transaction that attempts to send all the + // provided [outputs] to the requested [chainID]. + // + // - [chainID] specifies the chain to be exporting the funds to. + // - [outputs] specifies the outputs to send to the [chainID]. + // - [baseFee] specifies the fee price willing to be paid by this tx. + NewExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + baseFee *big.Int, + options ...common.Option, + ) (*evm.UnsignedExportTx, error) +} + +// BuilderBackend specifies the required information needed to build unsigned +// C-chain transactions. +type BuilderBackend interface { + Context + + UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) + Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) + Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) +} + +type builder struct { + avaxAddrs set.Set[ids.ShortID] + ethAddrs set.Set[ethcommon.Address] + backend BuilderBackend +} + +// NewBuilder returns a new transaction builder. +// +// - [avaxAddrs] is the set of addresses in the AVAX format that the builder +// assumes can be used when signing the transactions in the future. +// - [ethAddrs] is the set of addresses in the Eth format that the builder +// assumes can be used when signing the transactions in the future. +// - [backend] provides the required access to the chain's context and state +// to build out the transactions. +func NewBuilder( + avaxAddrs set.Set[ids.ShortID], + ethAddrs set.Set[ethcommon.Address], + backend BuilderBackend, +) Builder { + return &builder{ + avaxAddrs: avaxAddrs, + ethAddrs: ethAddrs, + backend: backend, + } +} + +func (b *builder) GetBalance( + options ...common.Option, +) (*big.Int, error) { + var ( + ops = common.NewOptions(options) + ctx = ops.Context() + addrs = ops.EthAddresses(b.ethAddrs) + totalBalance = new(big.Int) + ) + for addr := range addrs { + balance, err := b.backend.Balance(ctx, addr) + if err != nil { + return nil, err + } + totalBalance.Add(totalBalance, balance) + } + + return totalBalance, nil +} + +func (b *builder) GetImportableBalance( + chainID ids.ID, + options ...common.Option, +) (uint64, error) { + ops := common.NewOptions(options) + utxos, err := b.backend.UTXOs(ops.Context(), chainID) + if err != nil { + return 0, err + } + + var ( + addrs = ops.Addresses(b.avaxAddrs) + minIssuanceTime = ops.MinIssuanceTime() + avaxAssetID = b.backend.AVAXAssetID() + balance uint64 + ) + for _, utxo := range utxos { + amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) + if !ok { + continue + } + + newBalance, err := math.Add64(balance, amount) + if err != nil { + return 0, err + } + balance = newBalance + } + + return balance, nil +} + +func (b *builder) NewImportTx( + chainID ids.ID, + to ethcommon.Address, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedImportTx, error) { + ops := common.NewOptions(options) + utxos, err := b.backend.UTXOs(ops.Context(), chainID) + if err != nil { + return nil, err + } + + var ( + addrs = ops.Addresses(b.avaxAddrs) + minIssuanceTime = ops.MinIssuanceTime() + avaxAssetID = b.backend.AVAXAssetID() + + importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) + importedAmount uint64 + ) + for _, utxo := range utxos { + amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) + if !ok { + continue + } + + importedInputs = append(importedInputs, &avax.TransferableInput{ + UTXOID: utxo.UTXOID, + Asset: utxo.Asset, + In: &secp256k1fx.TransferInput{ + Amt: amount, + Input: secp256k1fx.Input{ + SigIndices: inputSigIndices, + }, + }, + }) + + newImportedAmount, err := math.Add64(importedAmount, amount) + if err != nil { + return nil, err + } + importedAmount = newImportedAmount + } + + utils.Sort(importedInputs) + tx := &evm.UnsignedImportTx{ + NetworkID: b.backend.NetworkID(), + BlockchainID: b.backend.BlockchainID(), + SourceChain: chainID, + ImportedInputs: importedInputs, + } + + // We must initialize the bytes of the tx to calculate the initial cost + wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} + if err := wrappedTx.Sign(evm.Codec, nil); err != nil { + return nil, err + } + + gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) + if err != nil { + return nil, err + } + gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas + + txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) + if err != nil { + return nil, err + } + + if importedAmount <= txFee { + return nil, errInsufficientFunds + } + + tx.Outs = []evm.EVMOutput{{ + Address: to, + Amount: importedAmount - txFee, + AssetID: avaxAssetID, + }} + return tx, nil +} + +func (b *builder) NewExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedExportTx, error) { + var ( + avaxAssetID = b.backend.AVAXAssetID() + exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) + exportedAmount uint64 + ) + for i, output := range outputs { + exportedOutputs[i] = &avax.TransferableOutput{ + Asset: avax.Asset{ID: avaxAssetID}, + Out: output, + } + + newExportedAmount, err := math.Add64(exportedAmount, output.Amt) + if err != nil { + return nil, err + } + exportedAmount = newExportedAmount + } + + avax.SortTransferableOutputs(exportedOutputs, evm.Codec) + tx := &evm.UnsignedExportTx{ + NetworkID: b.backend.NetworkID(), + BlockchainID: b.backend.BlockchainID(), + DestinationChain: chainID, + ExportedOutputs: exportedOutputs, + } + + // We must initialize the bytes of the tx to calculate the initial cost + wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} + if err := wrappedTx.Sign(evm.Codec, nil); err != nil { + return nil, err + } + + cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) + if err != nil { + return nil, err + } + + initialFee, err := evm.CalculateDynamicFee(cost, baseFee) + if err != nil { + return nil, err + } + + amountToConsume, err := math.Add64(exportedAmount, initialFee) + if err != nil { + return nil, err + } + + var ( + ops = common.NewOptions(options) + ctx = ops.Context() + addrs = ops.EthAddresses(b.ethAddrs) + inputs = make([]evm.EVMInput, 0, addrs.Len()) + ) + for addr := range addrs { + if amountToConsume == 0 { + break + } + + prevFee, err := evm.CalculateDynamicFee(cost, baseFee) + if err != nil { + return nil, err + } + + newCost := cost + evm.EVMInputGas + newFee, err := evm.CalculateDynamicFee(newCost, baseFee) + if err != nil { + return nil, err + } + + additionalFee := newFee - prevFee + + balance, err := b.backend.Balance(ctx, addr) + if err != nil { + return nil, err + } + + // Since the asset is AVAX, we divide by the avaxConversionRate to + // convert back to the correct denomination of AVAX that can be + // exported. + avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() + + // If the balance for [addr] is insufficient to cover the additional + // cost of adding an input to the transaction, skip adding the input + // altogether. + if avaxBalance <= additionalFee { + continue + } + + // Update the cost for the next iteration + cost = newCost + + amountToConsume, err = math.Add64(amountToConsume, additionalFee) + if err != nil { + return nil, err + } + + nonce, err := b.backend.Nonce(ctx, addr) + if err != nil { + return nil, err + } + + inputAmount := math.Min(amountToConsume, avaxBalance) + inputs = append(inputs, evm.EVMInput{ + Address: addr, + Amount: inputAmount, + AssetID: avaxAssetID, + Nonce: nonce, + }) + amountToConsume -= inputAmount + } + + if amountToConsume > 0 { + return nil, errInsufficientFunds + } + + utils.Sort(inputs) + tx.Ins = inputs + return tx, nil +} + +func getSpendableAmount( + utxo *avax.UTXO, + addrs set.Set[ids.ShortID], + minIssuanceTime uint64, + avaxAssetID ids.ID, +) (uint64, []uint32, bool) { + if utxo.Asset.ID != avaxAssetID { + // Only AVAX can be imported + return 0, nil, false + } + + out, ok := utxo.Out.(*secp256k1fx.TransferOutput) + if !ok { + // Can't import an unknown transfer output type + return 0, nil, false + } + + inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) + return out.Amt, inputSigIndices, ok +} diff --git a/wallet/chain/c/builder_with_options.go b/wallet/chain/c/builder_with_options.go index 9b7ab8399484..8416dddf9928 100644 --- a/wallet/chain/c/builder_with_options.go +++ b/wallet/chain/c/builder_with_options.go @@ -3,81 +3,81 @@ package c -// import ( -// "math/big" +import ( + "math/big" -// "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/coreth/plugin/evm" -// ethcommon "github.com/ethereum/go-ethereum/common" + ethcommon "github.com/ethereum/go-ethereum/common" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) -// var _ Builder = (*builderWithOptions)(nil) +var _ Builder = (*builderWithOptions)(nil) -// type builderWithOptions struct { -// Builder -// options []common.Option -// } +type builderWithOptions struct { + Builder + options []common.Option +} -// // NewBuilderWithOptions returns a new transaction builder that will use the -// // given options by default. -// // -// // - [builder] is the builder that will be called to perform the underlying -// // operations. -// // - [options] will be provided to the builder in addition to the options -// // provided in the method calls. -// func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { -// return &builderWithOptions{ -// Builder: builder, -// options: options, -// } -// } +// NewBuilderWithOptions returns a new transaction builder that will use the +// given options by default. +// +// - [builder] is the builder that will be called to perform the underlying +// operations. +// - [options] will be provided to the builder in addition to the options +// provided in the method calls. +func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { + return &builderWithOptions{ + Builder: builder, + options: options, + } +} -// func (b *builderWithOptions) GetBalance( -// options ...common.Option, -// ) (*big.Int, error) { -// return b.Builder.GetBalance( -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) GetBalance( + options ...common.Option, +) (*big.Int, error) { + return b.Builder.GetBalance( + common.UnionOptions(b.options, options)..., + ) +} -// func (b *builderWithOptions) GetImportableBalance( -// chainID ids.ID, -// options ...common.Option, -// ) (uint64, error) { -// return b.Builder.GetImportableBalance( -// chainID, -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) GetImportableBalance( + chainID ids.ID, + options ...common.Option, +) (uint64, error) { + return b.Builder.GetImportableBalance( + chainID, + common.UnionOptions(b.options, options)..., + ) +} -// func (b *builderWithOptions) NewImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedImportTx, error) { -// return b.Builder.NewImportTx( -// chainID, -// to, -// baseFee, -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) NewImportTx( + chainID ids.ID, + to ethcommon.Address, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedImportTx, error) { + return b.Builder.NewImportTx( + chainID, + to, + baseFee, + common.UnionOptions(b.options, options)..., + ) +} -// func (b *builderWithOptions) NewExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedExportTx, error) { -// return b.Builder.NewExportTx( -// chainID, -// outputs, -// baseFee, -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) NewExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedExportTx, error) { + return b.Builder.NewExportTx( + chainID, + outputs, + baseFee, + common.UnionOptions(b.options, options)..., + ) +} diff --git a/wallet/chain/c/context.go b/wallet/chain/c/context.go index 1c01d8fb55c8..d506b42f81fa 100644 --- a/wallet/chain/c/context.go +++ b/wallet/chain/c/context.go @@ -3,81 +3,81 @@ package c -// import ( -// stdcontext "context" +import ( + stdcontext "context" -// "github.com/ava-labs/avalanchego/api/info" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/avm" -// ) + "github.com/ava-labs/avalanchego/api/info" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/avm" +) -// var _ Context = (*context)(nil) +var _ Context = (*context)(nil) -// type Context interface { -// NetworkID() uint32 -// BlockchainID() ids.ID -// AVAXAssetID() ids.ID -// } +type Context interface { + NetworkID() uint32 + BlockchainID() ids.ID + AVAXAssetID() ids.ID +} -// type context struct { -// networkID uint32 -// blockchainID ids.ID -// avaxAssetID ids.ID -// } +type context struct { + networkID uint32 + blockchainID ids.ID + avaxAssetID ids.ID +} -// func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { -// infoClient := info.NewClient(uri) -// xChainClient := avm.NewClient(uri, "X") -// return NewContextFromClients(ctx, infoClient, xChainClient) -// } +func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { + infoClient := info.NewClient(uri) + xChainClient := avm.NewClient(uri, "X") + return NewContextFromClients(ctx, infoClient, xChainClient) +} -// func NewContextFromClients( -// ctx stdcontext.Context, -// infoClient info.Client, -// xChainClient avm.Client, -// ) (Context, error) { -// networkID, err := infoClient.GetNetworkID(ctx) -// if err != nil { -// return nil, err -// } +func NewContextFromClients( + ctx stdcontext.Context, + infoClient info.Client, + xChainClient avm.Client, +) (Context, error) { + networkID, err := infoClient.GetNetworkID(ctx) + if err != nil { + return nil, err + } -// chainID, err := infoClient.GetBlockchainID(ctx, "C") -// if err != nil { -// return nil, err -// } + chainID, err := infoClient.GetBlockchainID(ctx, "C") + if err != nil { + return nil, err + } -// asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") -// if err != nil { -// return nil, err -// } + asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") + if err != nil { + return nil, err + } -// return NewContext( -// networkID, -// chainID, -// asset.AssetID, -// ), nil -// } + return NewContext( + networkID, + chainID, + asset.AssetID, + ), nil +} -// func NewContext( -// networkID uint32, -// blockchainID ids.ID, -// avaxAssetID ids.ID, -// ) Context { -// return &context{ -// networkID: networkID, -// blockchainID: blockchainID, -// avaxAssetID: avaxAssetID, -// } -// } +func NewContext( + networkID uint32, + blockchainID ids.ID, + avaxAssetID ids.ID, +) Context { + return &context{ + networkID: networkID, + blockchainID: blockchainID, + avaxAssetID: avaxAssetID, + } +} -// func (c *context) NetworkID() uint32 { -// return c.networkID -// } +func (c *context) NetworkID() uint32 { + return c.networkID +} -// func (c *context) BlockchainID() ids.ID { -// return c.blockchainID -// } +func (c *context) BlockchainID() ids.ID { + return c.blockchainID +} -// func (c *context) AVAXAssetID() ids.ID { -// return c.avaxAssetID -// } +func (c *context) AVAXAssetID() ids.ID { + return c.avaxAssetID +} diff --git a/wallet/chain/c/signer.go b/wallet/chain/c/signer.go index 4bedc378234b..4fd85ed3b532 100644 --- a/wallet/chain/c/signer.go +++ b/wallet/chain/c/signer.go @@ -3,221 +3,221 @@ package c -// import ( -// "errors" -// "fmt" - -// stdcontext "context" - -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/database" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils/crypto/keychain" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/hashing" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/components/verify" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// ) - -// const version = 0 - -// var ( -// _ Signer = (*txSigner)(nil) - -// errUnknownInputType = errors.New("unknown input type") -// errUnknownCredentialType = errors.New("unknown credential type") -// errUnknownOutputType = errors.New("unknown output type") -// errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") - -// emptySig [secp256k1.SignatureLen]byte -// ) - -// type Signer interface { -// SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) -// SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error -// } - -// type EthKeychain interface { -// // The returned Signer can provide a signature for [addr] -// GetEth(addr ethcommon.Address) (keychain.Signer, bool) -// // Returns the set of addresses for which the accessor keeps an associated -// // signer -// EthAddresses() set.Set[ethcommon.Address] -// } - -// type SignerBackend interface { -// GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) -// } - -// type txSigner struct { -// avaxKC keychain.Keychain -// ethKC EthKeychain -// backend SignerBackend -// } - -// func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { -// return &txSigner{ -// avaxKC: avaxKC, -// ethKC: ethKC, -// backend: backend, -// } -// } - -// func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { -// tx := &evm.Tx{UnsignedAtomicTx: utx} -// return tx, s.SignAtomic(ctx, tx) -// } - -// func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { -// switch utx := tx.UnsignedAtomicTx.(type) { -// case *evm.UnsignedImportTx: -// signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) -// if err != nil { -// return err -// } -// return sign(tx, true, signers) -// case *evm.UnsignedExportTx: -// signers := s.getExportSigners(utx.Ins) -// return sign(tx, true, signers) -// default: -// return fmt.Errorf("%w: %T", errUnknownTxType, tx) -// } -// } - -// func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { -// txSigners := make([][]keychain.Signer, len(ins)) -// for credIndex, transferInput := range ins { -// input, ok := transferInput.In.(*secp256k1fx.TransferInput) -// if !ok { -// return nil, errUnknownInputType -// } - -// inputSigners := make([]keychain.Signer, len(input.SigIndices)) -// txSigners[credIndex] = inputSigners - -// utxoID := transferInput.InputID() -// utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) -// if err == database.ErrNotFound { -// // If we don't have access to the UTXO, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// if err != nil { -// return nil, err -// } - -// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) -// if !ok { -// return nil, errUnknownOutputType -// } - -// for sigIndex, addrIndex := range input.SigIndices { -// if addrIndex >= uint32(len(out.Addrs)) { -// return nil, errInvalidUTXOSigIndex -// } - -// addr := out.Addrs[addrIndex] -// key, ok := s.avaxKC.Get(addr) -// if !ok { -// // If we don't have access to the key, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// inputSigners[sigIndex] = key -// } -// } -// return txSigners, nil -// } - -// func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { -// txSigners := make([][]keychain.Signer, len(ins)) -// for credIndex, input := range ins { -// inputSigners := make([]keychain.Signer, 1) -// txSigners[credIndex] = inputSigners - -// key, ok := s.ethKC.GetEth(input.Address) -// if !ok { -// // If we don't have access to the key, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// inputSigners[0] = key -// } -// return txSigners -// } - -// // TODO: remove [signHash] after the ledger supports signing all transactions. -// func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { -// unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) -// if err != nil { -// return fmt.Errorf("couldn't marshal unsigned tx: %w", err) -// } -// unsignedHash := hashing.ComputeHash256(unsignedBytes) - -// if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { -// tx.Creds = make([]verify.Verifiable, expectedLen) -// } - -// sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) -// for credIndex, inputSigners := range txSigners { -// credIntf := tx.Creds[credIndex] -// if credIntf == nil { -// credIntf = &secp256k1fx.Credential{} -// tx.Creds[credIndex] = credIntf -// } - -// cred, ok := credIntf.(*secp256k1fx.Credential) -// if !ok { -// return errUnknownCredentialType -// } -// if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { -// cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) -// } - -// for sigIndex, signer := range inputSigners { -// if signer == nil { -// // If we don't have access to the key, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// addr := signer.Address() -// if sig := cred.Sigs[sigIndex]; sig != emptySig { -// // If this signature has already been populated, we can just -// // copy the needed signature for the future. -// sigCache[addr] = sig -// continue -// } - -// if sig, exists := sigCache[addr]; exists { -// // If this key has already produced a signature, we can just -// // copy the previous signature. -// cred.Sigs[sigIndex] = sig -// continue -// } - -// var sig []byte -// if signHash { -// sig, err = signer.SignHash(unsignedHash) -// } else { -// sig, err = signer.Sign(unsignedBytes) -// } -// if err != nil { -// return fmt.Errorf("problem signing tx: %w", err) -// } -// copy(cred.Sigs[sigIndex][:], sig) -// sigCache[addr] = cred.Sigs[sigIndex] -// } -// } - -// signedBytes, err := evm.Codec.Marshal(version, tx) -// if err != nil { -// return fmt.Errorf("couldn't marshal tx: %w", err) -// } -// tx.Initialize(unsignedBytes, signedBytes) -// return nil -// } +import ( + "errors" + "fmt" + + stdcontext "context" + + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/crypto/keychain" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/hashing" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/components/verify" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" +) + +const version = 0 + +var ( + _ Signer = (*txSigner)(nil) + + errUnknownInputType = errors.New("unknown input type") + errUnknownCredentialType = errors.New("unknown credential type") + errUnknownOutputType = errors.New("unknown output type") + errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") + + emptySig [secp256k1.SignatureLen]byte +) + +type Signer interface { + SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) + SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error +} + +type EthKeychain interface { + // The returned Signer can provide a signature for [addr] + GetEth(addr ethcommon.Address) (keychain.Signer, bool) + // Returns the set of addresses for which the accessor keeps an associated + // signer + EthAddresses() set.Set[ethcommon.Address] +} + +type SignerBackend interface { + GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) +} + +type txSigner struct { + avaxKC keychain.Keychain + ethKC EthKeychain + backend SignerBackend +} + +func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { + return &txSigner{ + avaxKC: avaxKC, + ethKC: ethKC, + backend: backend, + } +} + +func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { + tx := &evm.Tx{UnsignedAtomicTx: utx} + return tx, s.SignAtomic(ctx, tx) +} + +func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { + switch utx := tx.UnsignedAtomicTx.(type) { + case *evm.UnsignedImportTx: + signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) + if err != nil { + return err + } + return sign(tx, true, signers) + case *evm.UnsignedExportTx: + signers := s.getExportSigners(utx.Ins) + return sign(tx, true, signers) + default: + return fmt.Errorf("%w: %T", errUnknownTxType, tx) + } +} + +func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { + txSigners := make([][]keychain.Signer, len(ins)) + for credIndex, transferInput := range ins { + input, ok := transferInput.In.(*secp256k1fx.TransferInput) + if !ok { + return nil, errUnknownInputType + } + + inputSigners := make([]keychain.Signer, len(input.SigIndices)) + txSigners[credIndex] = inputSigners + + utxoID := transferInput.InputID() + utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) + if err == database.ErrNotFound { + // If we don't have access to the UTXO, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + if err != nil { + return nil, err + } + + out, ok := utxo.Out.(*secp256k1fx.TransferOutput) + if !ok { + return nil, errUnknownOutputType + } + + for sigIndex, addrIndex := range input.SigIndices { + if addrIndex >= uint32(len(out.Addrs)) { + return nil, errInvalidUTXOSigIndex + } + + addr := out.Addrs[addrIndex] + key, ok := s.avaxKC.Get(addr) + if !ok { + // If we don't have access to the key, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + inputSigners[sigIndex] = key + } + } + return txSigners, nil +} + +func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { + txSigners := make([][]keychain.Signer, len(ins)) + for credIndex, input := range ins { + inputSigners := make([]keychain.Signer, 1) + txSigners[credIndex] = inputSigners + + key, ok := s.ethKC.GetEth(input.Address) + if !ok { + // If we don't have access to the key, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + inputSigners[0] = key + } + return txSigners +} + +// TODO: remove [signHash] after the ledger supports signing all transactions. +func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { + unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) + if err != nil { + return fmt.Errorf("couldn't marshal unsigned tx: %w", err) + } + unsignedHash := hashing.ComputeHash256(unsignedBytes) + + if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { + tx.Creds = make([]verify.Verifiable, expectedLen) + } + + sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) + for credIndex, inputSigners := range txSigners { + credIntf := tx.Creds[credIndex] + if credIntf == nil { + credIntf = &secp256k1fx.Credential{} + tx.Creds[credIndex] = credIntf + } + + cred, ok := credIntf.(*secp256k1fx.Credential) + if !ok { + return errUnknownCredentialType + } + if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { + cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) + } + + for sigIndex, signer := range inputSigners { + if signer == nil { + // If we don't have access to the key, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + addr := signer.Address() + if sig := cred.Sigs[sigIndex]; sig != emptySig { + // If this signature has already been populated, we can just + // copy the needed signature for the future. + sigCache[addr] = sig + continue + } + + if sig, exists := sigCache[addr]; exists { + // If this key has already produced a signature, we can just + // copy the previous signature. + cred.Sigs[sigIndex] = sig + continue + } + + var sig []byte + if signHash { + sig, err = signer.SignHash(unsignedHash) + } else { + sig, err = signer.Sign(unsignedBytes) + } + if err != nil { + return fmt.Errorf("problem signing tx: %w", err) + } + copy(cred.Sigs[sigIndex][:], sig) + sigCache[addr] = cred.Sigs[sigIndex] + } + } + + signedBytes, err := evm.Codec.Marshal(version, tx) + if err != nil { + return fmt.Errorf("couldn't marshal tx: %w", err) + } + tx.Initialize(unsignedBytes, signedBytes) + return nil +} diff --git a/wallet/chain/c/wallet.go b/wallet/chain/c/wallet.go index ebee50a9a958..fb1a83d53dad 100644 --- a/wallet/chain/c/wallet.go +++ b/wallet/chain/c/wallet.go @@ -3,204 +3,204 @@ package c -// import ( -// "errors" -// "math/big" -// "time" - -// "github.com/ava-labs/coreth/ethclient" -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var ( -// _ Wallet = (*wallet)(nil) - -// errNotCommitted = errors.New("not committed") -// ) - -// type Wallet interface { -// Context - -// // Builder returns the builder that will be used to create the transactions. -// Builder() Builder - -// // Signer returns the signer that will be used to sign the transactions. -// Signer() Signer - -// // IssueImportTx creates, signs, and issues an import transaction that -// // attempts to consume all the available UTXOs and import the funds to [to]. -// // -// // - [chainID] specifies the chain to be importing funds from. -// // - [to] specifies where to send the imported funds to. -// IssueImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// options ...common.Option, -// ) (*evm.Tx, error) - -// // IssueExportTx creates, signs, and issues an export transaction that -// // attempts to send all the provided [outputs] to the requested [chainID]. -// // -// // - [chainID] specifies the chain to be exporting the funds to. -// // - [outputs] specifies the outputs to send to the [chainID]. -// IssueExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// options ...common.Option, -// ) (*evm.Tx, error) - -// // IssueUnsignedTx signs and issues the unsigned tx. -// IssueUnsignedAtomicTx( -// utx evm.UnsignedAtomicTx, -// options ...common.Option, -// ) (*evm.Tx, error) - -// // IssueAtomicTx issues the signed tx. -// IssueAtomicTx( -// tx *evm.Tx, -// options ...common.Option, -// ) error -// } - -// func NewWallet( -// builder Builder, -// signer Signer, -// avaxClient evm.Client, -// ethClient ethclient.Client, -// backend Backend, -// ) Wallet { -// return &wallet{ -// Backend: backend, -// builder: builder, -// signer: signer, -// avaxClient: avaxClient, -// ethClient: ethClient, -// } -// } - -// type wallet struct { -// Backend -// builder Builder -// signer Signer -// avaxClient evm.Client -// ethClient ethclient.Client -// } - -// func (w *wallet) Builder() Builder { -// return w.builder -// } - -// func (w *wallet) Signer() Signer { -// return w.signer -// } - -// func (w *wallet) IssueImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// options ...common.Option, -// ) (*evm.Tx, error) { -// baseFee, err := w.baseFee(options) -// if err != nil { -// return nil, err -// } - -// utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) -// if err != nil { -// return nil, err -// } -// return w.IssueUnsignedAtomicTx(utx, options...) -// } - -// func (w *wallet) IssueExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// options ...common.Option, -// ) (*evm.Tx, error) { -// baseFee, err := w.baseFee(options) -// if err != nil { -// return nil, err -// } - -// utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) -// if err != nil { -// return nil, err -// } -// return w.IssueUnsignedAtomicTx(utx, options...) -// } - -// func (w *wallet) IssueUnsignedAtomicTx( -// utx evm.UnsignedAtomicTx, -// options ...common.Option, -// ) (*evm.Tx, error) { -// ops := common.NewOptions(options) -// ctx := ops.Context() -// tx, err := w.signer.SignUnsignedAtomic(ctx, utx) -// if err != nil { -// return nil, err -// } - -// return tx, w.IssueAtomicTx(tx, options...) -// } - -// func (w *wallet) IssueAtomicTx( -// tx *evm.Tx, -// options ...common.Option, -// ) error { -// ops := common.NewOptions(options) -// ctx := ops.Context() -// txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) -// if err != nil { -// return err -// } - -// if f := ops.PostIssuanceFunc(); f != nil { -// f(txID) -// } - -// if ops.AssumeDecided() { -// return w.Backend.AcceptAtomicTx(ctx, tx) -// } - -// pollFrequency := ops.PollFrequency() -// ticker := time.NewTicker(pollFrequency) -// defer ticker.Stop() - -// for { -// status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) -// if err != nil { -// return err -// } - -// switch status { -// case evm.Accepted: -// return w.Backend.AcceptAtomicTx(ctx, tx) -// case evm.Dropped, evm.Unknown: -// return errNotCommitted -// } - -// // The tx is Processing. - -// select { -// case <-ticker.C: -// case <-ctx.Done(): -// return ctx.Err() -// } -// } -// } - -// func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { -// ops := common.NewOptions(options) -// baseFee := ops.BaseFee(nil) -// if baseFee != nil { -// return baseFee, nil -// } - -// ctx := ops.Context() -// return w.ethClient.EstimateBaseFee(ctx) -// } +import ( + "errors" + "math/big" + "time" + + "github.com/ava-labs/coreth/ethclient" + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var ( + _ Wallet = (*wallet)(nil) + + errNotCommitted = errors.New("not committed") +) + +type Wallet interface { + Context + + // Builder returns the builder that will be used to create the transactions. + Builder() Builder + + // Signer returns the signer that will be used to sign the transactions. + Signer() Signer + + // IssueImportTx creates, signs, and issues an import transaction that + // attempts to consume all the available UTXOs and import the funds to [to]. + // + // - [chainID] specifies the chain to be importing funds from. + // - [to] specifies where to send the imported funds to. + IssueImportTx( + chainID ids.ID, + to ethcommon.Address, + options ...common.Option, + ) (*evm.Tx, error) + + // IssueExportTx creates, signs, and issues an export transaction that + // attempts to send all the provided [outputs] to the requested [chainID]. + // + // - [chainID] specifies the chain to be exporting the funds to. + // - [outputs] specifies the outputs to send to the [chainID]. + IssueExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + options ...common.Option, + ) (*evm.Tx, error) + + // IssueUnsignedTx signs and issues the unsigned tx. + IssueUnsignedAtomicTx( + utx evm.UnsignedAtomicTx, + options ...common.Option, + ) (*evm.Tx, error) + + // IssueAtomicTx issues the signed tx. + IssueAtomicTx( + tx *evm.Tx, + options ...common.Option, + ) error +} + +func NewWallet( + builder Builder, + signer Signer, + avaxClient evm.Client, + ethClient ethclient.Client, + backend Backend, +) Wallet { + return &wallet{ + Backend: backend, + builder: builder, + signer: signer, + avaxClient: avaxClient, + ethClient: ethClient, + } +} + +type wallet struct { + Backend + builder Builder + signer Signer + avaxClient evm.Client + ethClient ethclient.Client +} + +func (w *wallet) Builder() Builder { + return w.builder +} + +func (w *wallet) Signer() Signer { + return w.signer +} + +func (w *wallet) IssueImportTx( + chainID ids.ID, + to ethcommon.Address, + options ...common.Option, +) (*evm.Tx, error) { + baseFee, err := w.baseFee(options) + if err != nil { + return nil, err + } + + utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) + if err != nil { + return nil, err + } + return w.IssueUnsignedAtomicTx(utx, options...) +} + +func (w *wallet) IssueExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + options ...common.Option, +) (*evm.Tx, error) { + baseFee, err := w.baseFee(options) + if err != nil { + return nil, err + } + + utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) + if err != nil { + return nil, err + } + return w.IssueUnsignedAtomicTx(utx, options...) +} + +func (w *wallet) IssueUnsignedAtomicTx( + utx evm.UnsignedAtomicTx, + options ...common.Option, +) (*evm.Tx, error) { + ops := common.NewOptions(options) + ctx := ops.Context() + tx, err := w.signer.SignUnsignedAtomic(ctx, utx) + if err != nil { + return nil, err + } + + return tx, w.IssueAtomicTx(tx, options...) +} + +func (w *wallet) IssueAtomicTx( + tx *evm.Tx, + options ...common.Option, +) error { + ops := common.NewOptions(options) + ctx := ops.Context() + txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) + if err != nil { + return err + } + + if f := ops.PostIssuanceFunc(); f != nil { + f(txID) + } + + if ops.AssumeDecided() { + return w.Backend.AcceptAtomicTx(ctx, tx) + } + + pollFrequency := ops.PollFrequency() + ticker := time.NewTicker(pollFrequency) + defer ticker.Stop() + + for { + status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) + if err != nil { + return err + } + + switch status { + case evm.Accepted: + return w.Backend.AcceptAtomicTx(ctx, tx) + case evm.Dropped, evm.Unknown: + return errNotCommitted + } + + // The tx is Processing. + + select { + case <-ticker.C: + case <-ctx.Done(): + return ctx.Err() + } + } +} + +func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { + ops := common.NewOptions(options) + baseFee := ops.BaseFee(nil) + if baseFee != nil { + return baseFee, nil + } + + ctx := ops.Context() + return w.ethClient.EstimateBaseFee(ctx) +} diff --git a/wallet/chain/c/wallet_with_options.go b/wallet/chain/c/wallet_with_options.go index fd69a6d4fd02..7d6193683d49 100644 --- a/wallet/chain/c/wallet_with_options.go +++ b/wallet/chain/c/wallet_with_options.go @@ -3,80 +3,80 @@ package c -// import ( -// "github.com/ava-labs/coreth/plugin/evm" +import ( + "github.com/ava-labs/coreth/plugin/evm" -// ethcommon "github.com/ethereum/go-ethereum/common" + ethcommon "github.com/ethereum/go-ethereum/common" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) -// var _ Wallet = (*walletWithOptions)(nil) +var _ Wallet = (*walletWithOptions)(nil) -// func NewWalletWithOptions( -// wallet Wallet, -// options ...common.Option, -// ) Wallet { -// return &walletWithOptions{ -// Wallet: wallet, -// options: options, -// } -// } +func NewWalletWithOptions( + wallet Wallet, + options ...common.Option, +) Wallet { + return &walletWithOptions{ + Wallet: wallet, + options: options, + } +} -// type walletWithOptions struct { -// Wallet -// options []common.Option -// } +type walletWithOptions struct { + Wallet + options []common.Option +} -// func (w *walletWithOptions) Builder() Builder { -// return NewBuilderWithOptions( -// w.Wallet.Builder(), -// w.options..., -// ) -// } +func (w *walletWithOptions) Builder() Builder { + return NewBuilderWithOptions( + w.Wallet.Builder(), + w.options..., + ) +} -// func (w *walletWithOptions) IssueImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// options ...common.Option, -// ) (*evm.Tx, error) { -// return w.Wallet.IssueImportTx( -// chainID, -// to, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueImportTx( + chainID ids.ID, + to ethcommon.Address, + options ...common.Option, +) (*evm.Tx, error) { + return w.Wallet.IssueImportTx( + chainID, + to, + common.UnionOptions(w.options, options)..., + ) +} -// func (w *walletWithOptions) IssueExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// options ...common.Option, -// ) (*evm.Tx, error) { -// return w.Wallet.IssueExportTx( -// chainID, -// outputs, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + options ...common.Option, +) (*evm.Tx, error) { + return w.Wallet.IssueExportTx( + chainID, + outputs, + common.UnionOptions(w.options, options)..., + ) +} -// func (w *walletWithOptions) IssueUnsignedAtomicTx( -// utx evm.UnsignedAtomicTx, -// options ...common.Option, -// ) (*evm.Tx, error) { -// return w.Wallet.IssueUnsignedAtomicTx( -// utx, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueUnsignedAtomicTx( + utx evm.UnsignedAtomicTx, + options ...common.Option, +) (*evm.Tx, error) { + return w.Wallet.IssueUnsignedAtomicTx( + utx, + common.UnionOptions(w.options, options)..., + ) +} -// func (w *walletWithOptions) IssueAtomicTx( -// tx *evm.Tx, -// options ...common.Option, -// ) error { -// return w.Wallet.IssueAtomicTx( -// tx, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueAtomicTx( + tx *evm.Tx, + options ...common.Option, +) error { + return w.Wallet.IssueAtomicTx( + tx, + common.UnionOptions(w.options, options)..., + ) +} diff --git a/wallet/subnet/primary/api.go b/wallet/subnet/primary/api.go index 3260c05a0a1b..3ac72c217884 100644 --- a/wallet/subnet/primary/api.go +++ b/wallet/subnet/primary/api.go @@ -5,6 +5,12 @@ package primary import ( "context" + "fmt" + + "github.com/ava-labs/coreth/ethclient" + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ethereum/go-ethereum/common" "github.com/ava-labs/avalanchego/api/info" "github.com/ava-labs/avalanchego/codec" @@ -16,6 +22,7 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm" "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" ) @@ -52,9 +59,9 @@ type AVAXState struct { PCTX p.Context XClient avm.Client XCTX x.Context - // CClient evm.Client - // CCTX c.Context - UTXOs UTXOs + CClient evm.Client + CCTX c.Context + UTXOs UTXOs } func FetchState( @@ -68,7 +75,7 @@ func FetchState( infoClient := info.NewClient(uri) pClient := platformvm.NewClient(uri) xClient := avm.NewClient(uri, "X") - // cClient := evm.NewCChainClient(uri) + cClient := evm.NewCChainClient(uri) pCTX, err := p.NewContextFromClients(ctx, infoClient, xClient) if err != nil { @@ -80,10 +87,10 @@ func FetchState( return nil, err } - // cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) - // if err != nil { - // return nil, err - // } + cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) + if err != nil { + return nil, err + } utxos := NewUTXOs() addrList := addrs.List() @@ -102,11 +109,11 @@ func FetchState( client: xClient, codec: x.Parser.Codec(), }, - // { - // id: cCTX.BlockchainID(), - // client: cClient, - // codec: evm.Codec, - // }, + { + id: cCTX.BlockchainID(), + client: cClient, + codec: evm.Codec, + }, } for _, destinationChain := range chains { for _, sourceChain := range chains { @@ -129,52 +136,52 @@ func FetchState( PCTX: pCTX, XClient: xClient, XCTX: xCTX, - // CClient: cClient, - // CCTX: cCTX, - UTXOs: utxos, + CClient: cClient, + CCTX: cCTX, + UTXOs: utxos, }, nil } -// type EthState struct { -// Client ethclient.Client -// Accounts map[common.Address]*c.Account -// } - -// func FetchEthState( -// ctx context.Context, -// uri string, -// addrs set.Set[common.Address], -// ) (*EthState, error) { -// path := fmt.Sprintf( -// "%s/ext/%s/C/rpc", -// uri, -// constants.ChainAliasPrefix, -// ) -// client, err := ethclient.Dial(path) -// if err != nil { -// return nil, err -// } - -// accounts := make(map[common.Address]*c.Account, addrs.Len()) -// for addr := range addrs { -// balance, err := client.BalanceAt(ctx, addr, nil) -// if err != nil { -// return nil, err -// } -// nonce, err := client.NonceAt(ctx, addr, nil) -// if err != nil { -// return nil, err -// } -// accounts[addr] = &c.Account{ -// Balance: balance, -// Nonce: nonce, -// } -// } -// return &EthState{ -// Client: client, -// Accounts: accounts, -// }, nil -// } +type EthState struct { + Client ethclient.Client + Accounts map[common.Address]*c.Account +} + +func FetchEthState( + ctx context.Context, + uri string, + addrs set.Set[common.Address], +) (*EthState, error) { + path := fmt.Sprintf( + "%s/ext/%s/C/rpc", + uri, + constants.ChainAliasPrefix, + ) + client, err := ethclient.Dial(path) + if err != nil { + return nil, err + } + + accounts := make(map[common.Address]*c.Account, addrs.Len()) + for addr := range addrs { + balance, err := client.BalanceAt(ctx, addr, nil) + if err != nil { + return nil, err + } + nonce, err := client.NonceAt(ctx, addr, nil) + if err != nil { + return nil, err + } + accounts[addr] = &c.Account{ + Balance: balance, + Nonce: nonce, + } + } + return &EthState{ + Client: client, + Accounts: accounts, + }, nil +} // AddAllUTXOs fetches all the UTXOs referenced by [addresses] that were sent // from [sourceChainID] to [destinationChainID] from the [client]. It then uses diff --git a/wallet/subnet/primary/example_test.go b/wallet/subnet/primary/example_test.go index 4a73e8c070b2..483c049d4ac0 100644 --- a/wallet/subnet/primary/example_test.go +++ b/wallet/subnet/primary/example_test.go @@ -30,7 +30,7 @@ func ExampleWallet() { wallet, err := MakeWallet(ctx, &WalletConfig{ URI: LocalAPIURI, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet with: %s\n", err) diff --git a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go index 21c081d2982b..d5e8ce422307 100644 --- a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go @@ -46,9 +46,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/add-primary-validator/main.go b/wallet/subnet/primary/examples/add-primary-validator/main.go index 13c28f995f63..a56dae23db3a 100644 --- a/wallet/subnet/primary/examples/add-primary-validator/main.go +++ b/wallet/subnet/primary/examples/add-primary-validator/main.go @@ -45,7 +45,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/c-chain-export/main.go b/wallet/subnet/primary/examples/c-chain-export/main.go index a6b9a0c810b8..fec55c899feb 100644 --- a/wallet/subnet/primary/examples/c-chain-export/main.go +++ b/wallet/subnet/primary/examples/c-chain-export/main.go @@ -3,70 +3,70 @@ package main -// import ( -// "context" -// "log" -// "time" +import ( + "context" + "log" + "time" -// "github.com/ava-labs/avalanchego/genesis" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary" -// ) + "github.com/ava-labs/avalanchego/genesis" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary" +) -// func main() { -// key := genesis.EWOQKey -// uri := primary.LocalAPIURI -// kc := secp256k1fx.NewKeychain(key) -// avaxAddr := key.Address() +func main() { + key := genesis.EWOQKey + uri := primary.LocalAPIURI + kc := secp256k1fx.NewKeychain(key) + avaxAddr := key.Address() -// ctx := context.Background() + ctx := context.Background() -// // MakeWallet fetches the available UTXOs owned by [kc] on the network that -// // [uri] is hosting. -// walletSyncStartTime := time.Now() -// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ -// URI: uri, -// AVAXKeychain: kc, -// EthKeychain: kc, -// }) -// if err != nil { -// log.Fatalf("failed to initialize wallet: %s\n", err) -// } -// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) + // MakeWallet fetches the available UTXOs owned by [kc] on the network that + // [uri] is hosting. + walletSyncStartTime := time.Now() + wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, + }) + if err != nil { + log.Fatalf("failed to initialize wallet: %s\n", err) + } + log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) -// // Get the P-chain wallet -// pWallet := wallet.P() -// cWallet := wallet.C() + // Get the P-chain wallet + pWallet := wallet.P() + cWallet := wallet.C() -// // Pull out useful constants to use when issuing transactions. -// cChainID := cWallet.BlockchainID() -// owner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// avaxAddr, -// }, -// } + // Pull out useful constants to use when issuing transactions. + cChainID := cWallet.BlockchainID() + owner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + avaxAddr, + }, + } -// exportStartTime := time.Now() -// exportTx, err := cWallet.IssueExportTx( -// constants.PlatformChainID, -// []*secp256k1fx.TransferOutput{{ -// Amt: units.Avax, -// OutputOwners: owner, -// }}, -// ) -// if err != nil { -// log.Fatalf("failed to issue export transaction: %s\n", err) -// } -// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) + exportStartTime := time.Now() + exportTx, err := cWallet.IssueExportTx( + constants.PlatformChainID, + []*secp256k1fx.TransferOutput{{ + Amt: units.Avax, + OutputOwners: owner, + }}, + ) + if err != nil { + log.Fatalf("failed to issue export transaction: %s\n", err) + } + log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) -// importStartTime := time.Now() -// importTx, err := pWallet.IssueImportTx(cChainID, &owner) -// if err != nil { -// log.Fatalf("failed to issue import transaction: %s\n", err) -// } -// log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) -// } + importStartTime := time.Now() + importTx, err := pWallet.IssueImportTx(cChainID, &owner) + if err != nil { + log.Fatalf("failed to issue import transaction: %s\n", err) + } + log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) +} diff --git a/wallet/subnet/primary/examples/c-chain-import/main.go b/wallet/subnet/primary/examples/c-chain-import/main.go index 2d9b8a244cb0..b4dc4e603eb3 100644 --- a/wallet/subnet/primary/examples/c-chain-import/main.go +++ b/wallet/subnet/primary/examples/c-chain-import/main.go @@ -3,75 +3,75 @@ package main -// import ( -// "context" -// "log" -// "time" +import ( + "context" + "log" + "time" -// "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/coreth/plugin/evm" -// "github.com/ava-labs/avalanchego/genesis" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary" -// ) + "github.com/ava-labs/avalanchego/genesis" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary" +) -// func main() { -// key := genesis.EWOQKey -// uri := primary.LocalAPIURI -// kc := secp256k1fx.NewKeychain(key) -// avaxAddr := key.Address() -// ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) +func main() { + key := genesis.EWOQKey + uri := primary.LocalAPIURI + kc := secp256k1fx.NewKeychain(key) + avaxAddr := key.Address() + ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) -// ctx := context.Background() + ctx := context.Background() -// // MakeWallet fetches the available UTXOs owned by [kc] on the network that -// // [uri] is hosting. -// walletSyncStartTime := time.Now() -// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ -// URI: uri, -// AVAXKeychain: kc, -// EthKeychain: kc, -// }) -// if err != nil { -// log.Fatalf("failed to initialize wallet: %s\n", err) -// } -// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) + // MakeWallet fetches the available UTXOs owned by [kc] on the network that + // [uri] is hosting. + walletSyncStartTime := time.Now() + wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, + }) + if err != nil { + log.Fatalf("failed to initialize wallet: %s\n", err) + } + log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) -// // Get the P-chain wallet -// pWallet := wallet.P() -// cWallet := wallet.C() + // Get the P-chain wallet + pWallet := wallet.P() + cWallet := wallet.C() -// // Pull out useful constants to use when issuing transactions. -// cChainID := cWallet.BlockchainID() -// avaxAssetID := cWallet.AVAXAssetID() -// owner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// avaxAddr, -// }, -// } + // Pull out useful constants to use when issuing transactions. + cChainID := cWallet.BlockchainID() + avaxAssetID := cWallet.AVAXAssetID() + owner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + avaxAddr, + }, + } -// exportStartTime := time.Now() -// exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ -// Asset: avax.Asset{ID: avaxAssetID}, -// Out: &secp256k1fx.TransferOutput{ -// Amt: units.Avax, -// OutputOwners: owner, -// }, -// }}) -// if err != nil { -// log.Fatalf("failed to issue export transaction: %s\n", err) -// } -// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) + exportStartTime := time.Now() + exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ + Asset: avax.Asset{ID: avaxAssetID}, + Out: &secp256k1fx.TransferOutput{ + Amt: units.Avax, + OutputOwners: owner, + }, + }}) + if err != nil { + log.Fatalf("failed to issue export transaction: %s\n", err) + } + log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) -// importStartTime := time.Now() -// importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) -// if err != nil { -// log.Fatalf("failed to issue import transaction: %s\n", err) -// } -// log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) -// } + importStartTime := time.Now() + importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) + if err != nil { + log.Fatalf("failed to issue import transaction: %s\n", err) + } + log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) +} diff --git a/wallet/subnet/primary/examples/create-asset/main.go b/wallet/subnet/primary/examples/create-asset/main.go index 0bccfbb5fc52..30804f083df6 100644 --- a/wallet/subnet/primary/examples/create-asset/main.go +++ b/wallet/subnet/primary/examples/create-asset/main.go @@ -30,7 +30,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-chain/main.go b/wallet/subnet/primary/examples/create-chain/main.go index 521a3cca53cf..5e6898a1b649 100644 --- a/wallet/subnet/primary/examples/create-chain/main.go +++ b/wallet/subnet/primary/examples/create-chain/main.go @@ -41,9 +41,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/create-locked-stakeable/main.go b/wallet/subnet/primary/examples/create-locked-stakeable/main.go index 92f1b5cb0e1b..e688968e9e8a 100644 --- a/wallet/subnet/primary/examples/create-locked-stakeable/main.go +++ b/wallet/subnet/primary/examples/create-locked-stakeable/main.go @@ -39,7 +39,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-subnet/main.go b/wallet/subnet/primary/examples/create-subnet/main.go index 3e8d69bc016a..add98ea7931c 100644 --- a/wallet/subnet/primary/examples/create-subnet/main.go +++ b/wallet/subnet/primary/examples/create-subnet/main.go @@ -28,7 +28,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/remove-subnet-validator/main.go b/wallet/subnet/primary/examples/remove-subnet-validator/main.go index 46f4b85124db..2842c7c0a790 100644 --- a/wallet/subnet/primary/examples/remove-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/remove-subnet-validator/main.go @@ -38,9 +38,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/wallet.go b/wallet/subnet/primary/wallet.go index de50d12f866b..54de390d029c 100644 --- a/wallet/subnet/primary/wallet.go +++ b/wallet/subnet/primary/wallet.go @@ -11,6 +11,7 @@ import ( "github.com/ava-labs/avalanchego/utils/crypto/keychain" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" @@ -22,13 +23,13 @@ var _ Wallet = (*wallet)(nil) type Wallet interface { P() p.Wallet X() x.Wallet - // C() c.Wallet + C() c.Wallet } type wallet struct { p p.Wallet x x.Wallet - // c c.Wallet + c c.Wallet } func (w *wallet) P() p.Wallet { @@ -39,16 +40,16 @@ func (w *wallet) X() x.Wallet { return w.x } -// func (w *wallet) C() c.Wallet { -// return w.c -// } +func (w *wallet) C() c.Wallet { + return w.c +} // Creates a new default wallet -func NewWallet(p p.Wallet, x x.Wallet /*, c c.Wallet*/) Wallet { +func NewWallet(p p.Wallet, x x.Wallet, c c.Wallet) Wallet { return &wallet{ p: p, x: x, - // c: c, + c: c, } } @@ -57,7 +58,7 @@ func NewWalletWithOptions(w Wallet, options ...common.Option) Wallet { return NewWallet( p.NewWalletWithOptions(w.P(), options...), x.NewWalletWithOptions(w.X(), options...), - // c.NewWalletWithOptions(w.C(), options...), + c.NewWalletWithOptions(w.C(), options...), ) } @@ -66,7 +67,7 @@ type WalletConfig struct { URI string // required // Keys to use for signing all transactions. AVAXKeychain keychain.Keychain // required - // EthKeychain c.EthKeychain // required + EthKeychain c.EthKeychain // required // Set of P-chain transactions that the wallet should know about to be able // to generate transactions. PChainTxs map[ids.ID]*txs.Tx // optional @@ -92,11 +93,11 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { return nil, err } - // ethAddrs := config.EthKeychain.EthAddresses() - // ethState, err := FetchEthState(ctx, config.URI, ethAddrs) - // if err != nil { - // return nil, err - // } + ethAddrs := config.EthKeychain.EthAddresses() + ethState, err := FetchEthState(ctx, config.URI, ethAddrs) + if err != nil { + return nil, err + } pChainTxs := config.PChainTxs if pChainTxs == nil { @@ -126,15 +127,15 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { xBuilder := x.NewBuilder(avaxAddrs, xBackend) xSigner := x.NewSigner(config.AVAXKeychain, xBackend) - // cChainID := avaxState.CCTX.BlockchainID() - // cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) - // cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) - // cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) - // cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) + cChainID := avaxState.CCTX.BlockchainID() + cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) + cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) + cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) + cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) return NewWallet( p.NewWallet(pBuilder, pSigner, avaxState.PClient, pBackend), x.NewWallet(xBuilder, xSigner, avaxState.XClient, xBackend), - // c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), + c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), ), nil } From 98d01e8d372aaef5dba81a35f387368ae4d68bf4 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Thu, 2 Nov 2023 19:16:48 +0100 Subject: [PATCH 33/36] temporarily cut coreth dependencies --- go.mod | 25 - go.sum | 76 -- node/node.go | 4 +- tests/e2e/c/dynamic_fees.go | 326 +++---- tests/e2e/c/interchain_workflow.go | 320 +++---- tests/e2e/p/interchain_workflow.go | 444 +++++----- tests/e2e/x/interchain_workflow.go | 296 +++---- tests/fixture/e2e/helpers.go | 110 ++- tests/fixture/testnet/config.go | 54 +- vms/example/xsvm/cmd/chain/create/cmd.go | 6 +- wallet/chain/c/backend.go | 300 +++---- wallet/chain/c/builder.go | 792 +++++++++--------- wallet/chain/c/builder_with_options.go | 136 +-- wallet/chain/c/context.go | 130 +-- wallet/chain/c/signer.go | 436 +++++----- wallet/chain/c/wallet.go | 402 ++++----- wallet/chain/c/wallet_with_options.go | 134 +-- wallet/subnet/primary/api.go | 119 ++- wallet/subnet/primary/example_test.go | 2 +- .../add-permissioned-subnet-validator/main.go | 6 +- .../examples/add-primary-validator/main.go | 2 +- .../primary/examples/c-chain-export/main.go | 118 +-- .../primary/examples/c-chain-import/main.go | 126 +-- .../primary/examples/create-asset/main.go | 2 +- .../primary/examples/create-chain/main.go | 6 +- .../examples/create-locked-stakeable/main.go | 2 +- .../primary/examples/create-subnet/main.go | 2 +- .../examples/remove-subnet-validator/main.go | 6 +- wallet/subnet/primary/wallet.go | 41 +- 29 files changed, 2153 insertions(+), 2270 deletions(-) diff --git a/go.mod b/go.mod index 7242e98db458..23b752198fdd 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,6 @@ require ( github.com/DataDog/zstd v1.5.2 github.com/Microsoft/go-winio v0.5.2 github.com/NYTimes/gziphandler v1.1.1 - github.com/ava-labs/coreth v0.12.8-rc.1.0.20231108120716-bb29d644e8fb github.com/ava-labs/ledger-avalanche/go v0.0.0-20231102202641-ae2ebdaeac34 github.com/btcsuite/btcd/btcutil v1.1.3 github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 @@ -75,7 +74,6 @@ require ( github.com/BurntSushi/toml v1.2.1 // indirect github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect - github.com/VictoriaMetrics/fastcache v1.10.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect @@ -83,44 +81,26 @@ require ( github.com/cockroachdb/errors v1.9.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/redact v1.1.3 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/deckarep/golang-set/v2 v2.1.0 // indirect - github.com/dlclark/regexp2 v1.7.0 // indirect - github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect - github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/frankban/quicktest v1.14.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect - github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect - github.com/go-stack/stack v1.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect - github.com/google/uuid v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 // indirect - github.com/hashicorp/go-bexpr v0.1.10 // indirect - github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/klauspost/compress v1.15.15 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/magiconair/properties v1.8.6 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/mitchellh/pointerstructure v1.2.0 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect @@ -128,17 +108,12 @@ require ( github.com/prometheus/common v0.39.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sanity-io/litter v1.5.1 // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/status-im/keycard-go v0.2.0 // indirect github.com/subosito/gotenv v1.3.0 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect - github.com/tyler-smith/go-bip39 v1.1.0 // indirect - github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa // indirect - github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/zondax/hid v0.9.2 // indirect github.com/zondax/ledger-go v0.14.3 // indirect diff --git a/go.sum b/go.sum index 57c724d85c31..2ae152b17faf 100644 --- a/go.sum +++ b/go.sum @@ -56,18 +56,12 @@ github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cq github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= -github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY= -github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/ava-labs/coreth v0.12.8-rc.1.0.20231108120716-bb29d644e8fb h1:fF29dpDn1JxkQ+uX8oNiEuEgJ/sLzdrAx9slSY9rIN0= -github.com/ava-labs/coreth v0.12.8-rc.1.0.20231108120716-bb29d644e8fb/go.mod h1:3nYchxy6KE8cPT3pcW3ArwqgGdvR0sowgZbL5IcLz8Q= github.com/ava-labs/ledger-avalanche/go v0.0.0-20231102202641-ae2ebdaeac34 h1:mg9Uw6oZFJKytJxgxnl3uxZOs/SB8CVHg6Io4Tf99Zc= github.com/ava-labs/ledger-avalanche/go v0.0.0-20231102202641-ae2ebdaeac34/go.mod h1:pJxaT9bUgeRNVmNRgtCHb7sFDIRKy7CzTQVi8gGNT6g= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= @@ -102,18 +96,13 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= @@ -145,16 +134,12 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= -github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= @@ -165,14 +150,6 @@ github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6ps github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= -github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= -github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= -github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= -github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -189,8 +166,6 @@ github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2 github.com/ethereum/go-ethereum v1.12.0/go.mod h1:/oo2X/dZLJjf2mJ6YT9wcWxa4nNJDBKDBU6sFIpx1Gs= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= -github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -199,8 +174,6 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= -github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= @@ -224,11 +197,7 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= -github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= @@ -313,14 +282,10 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= -github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -341,17 +306,11 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 h1:kr3j8iIMR4ywO/O0rvksXaJvauGGCMg2zAZIiNZ9uIQ= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0/go.mod h1:ummNFgdgLhhX7aIiy35vVmQNS0rWXknfPE0qe6fmFXg= -github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= -github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= -github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw= -github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e/go.mod h1:j9cQbcqHQujT0oKJ38PylVfqohClLr3CvDC+Qcg+lhU= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8= @@ -363,7 +322,6 @@ github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3 github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -405,7 +363,6 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -413,7 +370,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= @@ -424,17 +380,11 @@ github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -443,11 +393,8 @@ github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= -github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -466,8 +413,6 @@ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -535,8 +480,6 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sanity-io/litter v1.5.1 h1:dwnrSypP6q56o3lFxTU+t2fwQ9A+U5qrXVO4Qg9KwVU= github.com/sanity-io/litter v1.5.1/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0= @@ -572,8 +515,6 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= -github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= -github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -605,14 +546,10 @@ github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZF github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= -github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= -github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= -github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -624,8 +561,6 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1: github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= @@ -635,7 +570,6 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= @@ -731,7 +665,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -777,7 +710,6 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -801,7 +733,6 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -866,12 +797,8 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -888,7 +815,6 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -952,7 +878,6 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1077,7 +1002,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= diff --git a/node/node.go b/node/node.go index 06544e8f9e6b..98d697a66359 100644 --- a/node/node.go +++ b/node/node.go @@ -25,7 +25,7 @@ import ( "go.uber.org/zap" - coreth "github.com/ava-labs/coreth/plugin/evm" + // coreth "github.com/ava-labs/coreth/plugin/evm" "github.com/ava-labs/avalanchego/api/admin" "github.com/ava-labs/avalanchego/api/auth" @@ -1094,7 +1094,7 @@ func (n *Node) initVMs() error { CreateAssetTxFee: n.Config.CreateAssetTxFee, }, }), - vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), + // vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), n.VMManager.RegisterFactory(context.TODO(), secp256k1fx.ID, &secp256k1fx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), nftfx.ID, &nftfx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), propertyfx.ID, &propertyfx.Factory{}), diff --git a/tests/e2e/c/dynamic_fees.go b/tests/e2e/c/dynamic_fees.go index 8f15b6d43caf..8748dda7451d 100644 --- a/tests/e2e/c/dynamic_fees.go +++ b/tests/e2e/c/dynamic_fees.go @@ -3,166 +3,166 @@ package c -import ( - "math/big" - "strings" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/stretchr/testify/require" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/coreth/core/types" - "github.com/ava-labs/coreth/params" - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/tests" - "github.com/ava-labs/avalanchego/tests/fixture/e2e" - "github.com/ava-labs/avalanchego/tests/fixture/testnet" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -) - -// This test uses the compiled bin for `hashing.sol` as -// well as its ABI contained in `hashing_contract.go`. - -var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { - require := require.New(ginkgo.GinkgoT()) - - // Need a gas limit much larger than the standard 21_000 to enable - // the contract to induce a gas price increase - const largeGasLimit = uint64(8_000_000) - - // TODO(marun) What is the significance of this value? - gasTip := big.NewInt(1000 * params.GWei) - - ginkgo.It("should ensure that the gas price is affected by load", func() { - ginkgo.By("creating a new private network to ensure isolation from other tests") - privateNetwork := e2e.Env.NewPrivateNetwork() - - ginkgo.By("allocating a pre-funded key") - key := privateNetwork.GetConfig().FundedKeys[0] - ethAddress := evm.GetEthAddress(key) - - ginkgo.By("initializing a coreth client") - node := privateNetwork.GetNodes()[0] - nodeURI := testnet.NodeURI{ - NodeID: node.GetID(), - URI: node.GetProcessContext().URI, - } - ethClient := e2e.NewEthClient(nodeURI) - - ginkgo.By("initializing a transaction signer") - cChainID, err := ethClient.ChainID(e2e.DefaultContext()) - require.NoError(err) - signer := types.NewEIP155Signer(cChainID) - ecdsaKey := key.ToECDSA() - sign := func(tx *types.Transaction) *types.Transaction { - signedTx, err := types.SignTx(tx, signer, ecdsaKey) - require.NoError(err) - return signedTx - } - - var contractAddress common.Address - ginkgo.By("deploying an expensive contract", func() { - // Create transaction - nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) - require.NoError(err) - compiledContract := common.Hex2Bytes(hashingCompiledContract) - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - GasPrice: gasTip, - Gas: largeGasLimit, - Value: common.Big0, - Data: compiledContract, - }) - - // Send the transaction and wait for acceptance - signedTx := sign(tx) - receipt := e2e.SendEthTransaction(ethClient, signedTx) - - contractAddress = receipt.ContractAddress - }) - - var gasPrice *big.Int - ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { - // Evaluate the bytes representation of the contract - hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) - require.NoError(err) - contractData, err := hashingABI.Pack("hashIt") - require.NoError(err) - - var initialGasPrice *big.Int - e2e.Eventually(func() bool { - // Check the gas price - var err error - gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) - require.NoError(err) - if initialGasPrice == nil { - initialGasPrice = gasPrice - tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) - } else if gasPrice.Cmp(initialGasPrice) > 0 { - // Gas price has increased - tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) - return true - } - - // Create the transaction - nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) - require.NoError(err) - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - GasPrice: gasTip, - Gas: largeGasLimit, - To: &contractAddress, - Value: common.Big0, - Data: contractData, - }) - - // Send the transaction and wait for acceptance - signedTx := sign(tx) - _ = e2e.SendEthTransaction(ethClient, signedTx) - - // The gas price will be checked at the start of the next iteration - return false - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") - }) - - ginkgo.By("waiting for the gas price to decrease...", func() { - initialGasPrice := gasPrice - e2e.Eventually(func() bool { - var err error - gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) - require.NoError(err) - tests.Outf("{{blue}}.{{/}}") - return initialGasPrice.Cmp(gasPrice) > 0 - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") - tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) - }) - - ginkgo.By("sending funds at the current gas price", func() { - // Create a recipient address - recipientKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - recipientEthAddress := evm.GetEthAddress(recipientKey) - - // Create transaction - nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) - require.NoError(err) - tx := types.NewTx(&types.LegacyTx{ - Nonce: nonce, - GasPrice: gasPrice, - Gas: e2e.DefaultGasLimit, - To: &recipientEthAddress, - Value: common.Big0, - }) - - // Send the transaction and wait for acceptance - signedTx := sign(tx) - _ = e2e.SendEthTransaction(ethClient, signedTx) - }) - - e2e.CheckBootstrapIsPossible(privateNetwork) - }) -}) +// import ( +// "math/big" +// "strings" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/stretchr/testify/require" + +// "github.com/ethereum/go-ethereum/accounts/abi" +// "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/coreth/core/types" +// "github.com/ava-labs/coreth/params" +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/tests" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/tests/fixture/testnet" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// ) + +// // This test uses the compiled bin for `hashing.sol` as +// // well as its ABI contained in `hashing_contract.go`. + +// var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { +// require := require.New(ginkgo.GinkgoT()) + +// // Need a gas limit much larger than the standard 21_000 to enable +// // the contract to induce a gas price increase +// const largeGasLimit = uint64(8_000_000) + +// // TODO(marun) What is the significance of this value? +// gasTip := big.NewInt(1000 * params.GWei) + +// ginkgo.It("should ensure that the gas price is affected by load", func() { +// ginkgo.By("creating a new private network to ensure isolation from other tests") +// privateNetwork := e2e.Env.NewPrivateNetwork() + +// ginkgo.By("allocating a pre-funded key") +// key := privateNetwork.GetConfig().FundedKeys[0] +// ethAddress := evm.GetEthAddress(key) + +// ginkgo.By("initializing a coreth client") +// node := privateNetwork.GetNodes()[0] +// nodeURI := testnet.NodeURI{ +// NodeID: node.GetID(), +// URI: node.GetProcessContext().URI, +// } +// ethClient := e2e.NewEthClient(nodeURI) + +// ginkgo.By("initializing a transaction signer") +// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) +// require.NoError(err) +// signer := types.NewEIP155Signer(cChainID) +// ecdsaKey := key.ToECDSA() +// sign := func(tx *types.Transaction) *types.Transaction { +// signedTx, err := types.SignTx(tx, signer, ecdsaKey) +// require.NoError(err) +// return signedTx +// } + +// var contractAddress common.Address +// ginkgo.By("deploying an expensive contract", func() { +// // Create transaction +// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) +// require.NoError(err) +// compiledContract := common.Hex2Bytes(hashingCompiledContract) +// tx := types.NewTx(&types.LegacyTx{ +// Nonce: nonce, +// GasPrice: gasTip, +// Gas: largeGasLimit, +// Value: common.Big0, +// Data: compiledContract, +// }) + +// // Send the transaction and wait for acceptance +// signedTx := sign(tx) +// receipt := e2e.SendEthTransaction(ethClient, signedTx) + +// contractAddress = receipt.ContractAddress +// }) + +// var gasPrice *big.Int +// ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { +// // Evaluate the bytes representation of the contract +// hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) +// require.NoError(err) +// contractData, err := hashingABI.Pack("hashIt") +// require.NoError(err) + +// var initialGasPrice *big.Int +// e2e.Eventually(func() bool { +// // Check the gas price +// var err error +// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) +// require.NoError(err) +// if initialGasPrice == nil { +// initialGasPrice = gasPrice +// tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) +// } else if gasPrice.Cmp(initialGasPrice) > 0 { +// // Gas price has increased +// tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) +// return true +// } + +// // Create the transaction +// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) +// require.NoError(err) +// tx := types.NewTx(&types.LegacyTx{ +// Nonce: nonce, +// GasPrice: gasTip, +// Gas: largeGasLimit, +// To: &contractAddress, +// Value: common.Big0, +// Data: contractData, +// }) + +// // Send the transaction and wait for acceptance +// signedTx := sign(tx) +// _ = e2e.SendEthTransaction(ethClient, signedTx) + +// // The gas price will be checked at the start of the next iteration +// return false +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") +// }) + +// ginkgo.By("waiting for the gas price to decrease...", func() { +// initialGasPrice := gasPrice +// e2e.Eventually(func() bool { +// var err error +// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) +// require.NoError(err) +// tests.Outf("{{blue}}.{{/}}") +// return initialGasPrice.Cmp(gasPrice) > 0 +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") +// tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) +// }) + +// ginkgo.By("sending funds at the current gas price", func() { +// // Create a recipient address +// recipientKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) +// recipientEthAddress := evm.GetEthAddress(recipientKey) + +// // Create transaction +// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) +// require.NoError(err) +// tx := types.NewTx(&types.LegacyTx{ +// Nonce: nonce, +// GasPrice: gasPrice, +// Gas: e2e.DefaultGasLimit, +// To: &recipientEthAddress, +// Value: common.Big0, +// }) + +// // Send the transaction and wait for acceptance +// signedTx := sign(tx) +// _ = e2e.SendEthTransaction(ethClient, signedTx) +// }) + +// e2e.CheckBootstrapIsPossible(privateNetwork) +// }) +// }) diff --git a/tests/e2e/c/interchain_workflow.go b/tests/e2e/c/interchain_workflow.go index 2c9bd198ec39..8c019078ec6c 100644 --- a/tests/e2e/c/interchain_workflow.go +++ b/tests/e2e/c/interchain_workflow.go @@ -3,163 +3,163 @@ package c -import ( - "math/big" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/coreth/core/types" - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/tests/fixture/e2e" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { - require := require.New(ginkgo.GinkgoT()) - - const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer - - ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { - ginkgo.By("initializing a new eth client") - // Select a random node URI to use for both the eth client and - // the wallet to avoid having to verify that all nodes are at - // the same height before initializing the wallet. - nodeURI := e2e.Env.GetRandomNodeURI() - ethClient := e2e.NewEthClient(nodeURI) - - ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") - senderKey := e2e.Env.AllocateFundedKey() - senderEthAddress := evm.GetEthAddress(senderKey) - recipientKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - recipientEthAddress := evm.GetEthAddress(recipientKey) - - ginkgo.By("sending funds from one address to another on the C-Chain", func() { - // Create transaction - acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) - require.NoError(err) - gasPrice := e2e.SuggestGasPrice(ethClient) - tx := types.NewTransaction( - acceptedNonce, - recipientEthAddress, - big.NewInt(int64(txAmount)), - e2e.DefaultGasLimit, - gasPrice, - nil, - ) - - // Sign transaction - cChainID, err := ethClient.ChainID(e2e.DefaultContext()) - require.NoError(err) - signer := types.NewEIP155Signer(cChainID) - signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) - require.NoError(err) - - _ = e2e.SendEthTransaction(ethClient, signedTx) - - ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") - e2e.Eventually(func() bool { - balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) - require.NoError(err) - return balance.Cmp(big.NewInt(0)) > 0 - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") - }) - - // Wallet must be initialized after sending funds on the - // C-Chain with the same node URI to ensure wallet state - // matches on-chain state. - ginkgo.By("initializing a keychain and associated wallet") - keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) - baseWallet := e2e.NewWallet(keychain, nodeURI) - xWallet := baseWallet.X() - cWallet := baseWallet.C() - pWallet := baseWallet.P() - - ginkgo.By("defining common configuration") - avaxAssetID := xWallet.AVAXAssetID() - // Use the same owner for import funds to X-Chain and P-Chain - recipientOwner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - recipientKey.Address(), - }, - } - // Use the same outputs for both X-Chain and P-Chain exports - exportOutputs := []*secp256k1fx.TransferOutput{ - { - Amt: txAmount, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - keychain.Keys[0].Address(), - }, - }, - }, - } - - ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { - _, err := cWallet.IssueExportTx( - xWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { - _, err := xWallet.IssueImportTx( - cWallet.BlockchainID(), - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { - balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { - _, err := cWallet.IssueExportTx( - constants.PlatformChainID, - exportOutputs, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { - _, err = pWallet.IssueImportTx( - cWallet.BlockchainID(), - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { - balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) - }) -}) +// import ( +// "math/big" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/stretchr/testify/require" + +// "github.com/ava-labs/coreth/core/types" +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { +// require := require.New(ginkgo.GinkgoT()) + +// const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer + +// ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { +// ginkgo.By("initializing a new eth client") +// // Select a random node URI to use for both the eth client and +// // the wallet to avoid having to verify that all nodes are at +// // the same height before initializing the wallet. +// nodeURI := e2e.Env.GetRandomNodeURI() +// ethClient := e2e.NewEthClient(nodeURI) + +// ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") +// senderKey := e2e.Env.AllocateFundedKey() +// senderEthAddress := evm.GetEthAddress(senderKey) +// recipientKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) +// recipientEthAddress := evm.GetEthAddress(recipientKey) + +// ginkgo.By("sending funds from one address to another on the C-Chain", func() { +// // Create transaction +// acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) +// require.NoError(err) +// gasPrice := e2e.SuggestGasPrice(ethClient) +// tx := types.NewTransaction( +// acceptedNonce, +// recipientEthAddress, +// big.NewInt(int64(txAmount)), +// e2e.DefaultGasLimit, +// gasPrice, +// nil, +// ) + +// // Sign transaction +// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) +// require.NoError(err) +// signer := types.NewEIP155Signer(cChainID) +// signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) +// require.NoError(err) + +// _ = e2e.SendEthTransaction(ethClient, signedTx) + +// ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") +// e2e.Eventually(func() bool { +// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) +// require.NoError(err) +// return balance.Cmp(big.NewInt(0)) > 0 +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") +// }) + +// // Wallet must be initialized after sending funds on the +// // C-Chain with the same node URI to ensure wallet state +// // matches on-chain state. +// ginkgo.By("initializing a keychain and associated wallet") +// keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) +// baseWallet := e2e.NewWallet(keychain, nodeURI) +// xWallet := baseWallet.X() +// cWallet := baseWallet.C() +// pWallet := baseWallet.P() + +// ginkgo.By("defining common configuration") +// avaxAssetID := xWallet.AVAXAssetID() +// // Use the same owner for import funds to X-Chain and P-Chain +// recipientOwner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// recipientKey.Address(), +// }, +// } +// // Use the same outputs for both X-Chain and P-Chain exports +// exportOutputs := []*secp256k1fx.TransferOutput{ +// { +// Amt: txAmount, +// OutputOwners: secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// keychain.Keys[0].Address(), +// }, +// }, +// }, +// } + +// ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { +// _, err := cWallet.IssueExportTx( +// xWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { +// _, err := xWallet.IssueImportTx( +// cWallet.BlockchainID(), +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { +// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { +// _, err := cWallet.IssueExportTx( +// constants.PlatformChainID, +// exportOutputs, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { +// _, err = pWallet.IssueImportTx( +// cWallet.BlockchainID(), +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { +// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) +// }) +// }) diff --git a/tests/e2e/p/interchain_workflow.go b/tests/e2e/p/interchain_workflow.go index 44a6912715ef..33a8345f919f 100644 --- a/tests/e2e/p/interchain_workflow.go +++ b/tests/e2e/p/interchain_workflow.go @@ -3,225 +3,225 @@ package p -import ( - "math/big" - "time" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/spf13/cast" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/api/info" - "github.com/ava-labs/avalanchego/config" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/tests/fixture/e2e" - "github.com/ava-labs/avalanchego/tests/fixture/testnet" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/platformvm/reward" - "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { - require := require.New(ginkgo.GinkgoT()) - - const ( - transferAmount = 10 * units.Avax - weight = 2_000 * units.Avax // Used for both validation and delegation - ) - - ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { - network := e2e.Env.GetNetwork() - - ginkgo.By("checking that the network has a compatible minimum stake duration", func() { - minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) - require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) - }) - - ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") - recipientKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - keychain := e2e.Env.NewKeychain(1) - keychain.Add(recipientKey) - nodeURI := e2e.Env.GetRandomNodeURI() - baseWallet := e2e.NewWallet(keychain, nodeURI) - xWallet := baseWallet.X() - cWallet := baseWallet.C() - pWallet := baseWallet.P() - - ginkgo.By("defining common configuration") - recipientEthAddress := evm.GetEthAddress(recipientKey) - avaxAssetID := xWallet.AVAXAssetID() - // Use the same owner for sending to X-Chain and importing funds to P-Chain - recipientOwner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - recipientKey.Address(), - }, - } - // Use the same outputs for both X-Chain and C-Chain exports - exportOutputs := []*avax.TransferableOutput{ - { - Asset: avax.Asset{ - ID: avaxAssetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: transferAmount, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - keychain.Keys[0].Address(), - }, - }, - }, - }, - } - - ginkgo.By("adding new node and waiting for it to report healthy") - node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) - e2e.WaitForHealthy(node) - - ginkgo.By("retrieving new node's id and pop") - infoClient := info.NewClient(node.GetProcessContext().URI) - nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) - require.NoError(err) - - ginkgo.By("adding the new node as a validator", func() { - startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) - // Validation duration doesn't actually matter to this - // test - it is only ensuring that adding a validator - // doesn't break interchain transfer. - endTime := startTime.Add(30 * time.Second) - - rewardKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - - const ( - delegationPercent = 0.10 // 10% - delegationShare = reward.PercentDenominator * delegationPercent - ) - - _, err = pWallet.IssueAddPermissionlessValidatorTx( - &txs.SubnetValidator{ - Validator: txs.Validator{ - NodeID: nodeID, - Start: uint64(startTime.Unix()), - End: uint64(endTime.Unix()), - Wght: weight, - }, - Subnet: constants.PrimaryNetworkID, - }, - nodePOP, - pWallet.AVAXAssetID(), - &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{rewardKey.Address()}, - }, - &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{rewardKey.Address()}, - }, - delegationShare, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("adding a delegator to the new node", func() { - startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) - // Delegation duration doesn't actually matter to this - // test - it is only ensuring that adding a delegator - // doesn't break interchain transfer. - endTime := startTime.Add(15 * time.Second) - - rewardKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - - _, err = pWallet.IssueAddPermissionlessDelegatorTx( - &txs.SubnetValidator{ - Validator: txs.Validator{ - NodeID: nodeID, - Start: uint64(startTime.Unix()), - End: uint64(endTime.Unix()), - Wght: weight, - }, - Subnet: constants.PrimaryNetworkID, - }, - pWallet.AVAXAssetID(), - &secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{rewardKey.Address()}, - }, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { - _, err := pWallet.IssueExportTx( - xWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { - _, err := xWallet.IssueImportTx( - constants.PlatformChainID, - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { - balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { - _, err := pWallet.IssueExportTx( - cWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("initializing a new eth client") - ethClient := e2e.NewEthClient(nodeURI) - - ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { - _, err := cWallet.IssueImportTx( - constants.PlatformChainID, - recipientEthAddress, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") - balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) - require.NoError(err) - require.Positive(balance.Cmp(big.NewInt(0))) - - ginkgo.By("stopping validator node to free up resources for a bootstrap check") - require.NoError(node.Stop()) - - e2e.CheckBootstrapIsPossible(network) - }) -}) +// import ( +// "math/big" +// "time" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/spf13/cast" + +// "github.com/stretchr/testify/require" + +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/api/info" +// "github.com/ava-labs/avalanchego/config" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/tests/fixture/testnet" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/platformvm/reward" +// "github.com/ava-labs/avalanchego/vms/platformvm/txs" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { +// require := require.New(ginkgo.GinkgoT()) + +// const ( +// transferAmount = 10 * units.Avax +// weight = 2_000 * units.Avax // Used for both validation and delegation +// ) + +// ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { +// network := e2e.Env.GetNetwork() + +// ginkgo.By("checking that the network has a compatible minimum stake duration", func() { +// minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) +// require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) +// }) + +// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") +// recipientKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) +// keychain := e2e.Env.NewKeychain(1) +// keychain.Add(recipientKey) +// nodeURI := e2e.Env.GetRandomNodeURI() +// baseWallet := e2e.NewWallet(keychain, nodeURI) +// xWallet := baseWallet.X() +// cWallet := baseWallet.C() +// pWallet := baseWallet.P() + +// ginkgo.By("defining common configuration") +// recipientEthAddress := evm.GetEthAddress(recipientKey) +// avaxAssetID := xWallet.AVAXAssetID() +// // Use the same owner for sending to X-Chain and importing funds to P-Chain +// recipientOwner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// recipientKey.Address(), +// }, +// } +// // Use the same outputs for both X-Chain and C-Chain exports +// exportOutputs := []*avax.TransferableOutput{ +// { +// Asset: avax.Asset{ +// ID: avaxAssetID, +// }, +// Out: &secp256k1fx.TransferOutput{ +// Amt: transferAmount, +// OutputOwners: secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// keychain.Keys[0].Address(), +// }, +// }, +// }, +// }, +// } + +// ginkgo.By("adding new node and waiting for it to report healthy") +// node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) +// e2e.WaitForHealthy(node) + +// ginkgo.By("retrieving new node's id and pop") +// infoClient := info.NewClient(node.GetProcessContext().URI) +// nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) +// require.NoError(err) + +// ginkgo.By("adding the new node as a validator", func() { +// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) +// // Validation duration doesn't actually matter to this +// // test - it is only ensuring that adding a validator +// // doesn't break interchain transfer. +// endTime := startTime.Add(30 * time.Second) + +// rewardKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) + +// const ( +// delegationPercent = 0.10 // 10% +// delegationShare = reward.PercentDenominator * delegationPercent +// ) + +// _, err = pWallet.IssueAddPermissionlessValidatorTx( +// &txs.SubnetValidator{ +// Validator: txs.Validator{ +// NodeID: nodeID, +// Start: uint64(startTime.Unix()), +// End: uint64(endTime.Unix()), +// Wght: weight, +// }, +// Subnet: constants.PrimaryNetworkID, +// }, +// nodePOP, +// pWallet.AVAXAssetID(), +// &secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{rewardKey.Address()}, +// }, +// &secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{rewardKey.Address()}, +// }, +// delegationShare, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("adding a delegator to the new node", func() { +// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) +// // Delegation duration doesn't actually matter to this +// // test - it is only ensuring that adding a delegator +// // doesn't break interchain transfer. +// endTime := startTime.Add(15 * time.Second) + +// rewardKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) + +// _, err = pWallet.IssueAddPermissionlessDelegatorTx( +// &txs.SubnetValidator{ +// Validator: txs.Validator{ +// NodeID: nodeID, +// Start: uint64(startTime.Unix()), +// End: uint64(endTime.Unix()), +// Wght: weight, +// }, +// Subnet: constants.PrimaryNetworkID, +// }, +// pWallet.AVAXAssetID(), +// &secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{rewardKey.Address()}, +// }, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { +// _, err := pWallet.IssueExportTx( +// xWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { +// _, err := xWallet.IssueImportTx( +// constants.PlatformChainID, +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { +// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { +// _, err := pWallet.IssueExportTx( +// cWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("initializing a new eth client") +// ethClient := e2e.NewEthClient(nodeURI) + +// ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { +// _, err := cWallet.IssueImportTx( +// constants.PlatformChainID, +// recipientEthAddress, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") +// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) +// require.NoError(err) +// require.Positive(balance.Cmp(big.NewInt(0))) + +// ginkgo.By("stopping validator node to free up resources for a bootstrap check") +// require.NoError(node.Stop()) + +// e2e.CheckBootstrapIsPossible(network) +// }) +// }) diff --git a/tests/e2e/x/interchain_workflow.go b/tests/e2e/x/interchain_workflow.go index f0c2951feb84..99efca2eced0 100644 --- a/tests/e2e/x/interchain_workflow.go +++ b/tests/e2e/x/interchain_workflow.go @@ -3,151 +3,151 @@ package x -import ( - "math/big" - - ginkgo "github.com/onsi/ginkgo/v2" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/tests/fixture/e2e" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { - require := require.New(ginkgo.GinkgoT()) - - const transferAmount = 10 * units.Avax - - ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { - nodeURI := e2e.Env.GetRandomNodeURI() - - ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") - recipientKey, err := secp256k1.NewPrivateKey() - require.NoError(err) - keychain := e2e.Env.NewKeychain(1) - keychain.Add(recipientKey) - baseWallet := e2e.NewWallet(keychain, nodeURI) - xWallet := baseWallet.X() - cWallet := baseWallet.C() - pWallet := baseWallet.P() - - ginkgo.By("defining common configuration") - recipientEthAddress := evm.GetEthAddress(recipientKey) - avaxAssetID := xWallet.AVAXAssetID() - // Use the same owner for sending to X-Chain and importing funds to P-Chain - recipientOwner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - recipientKey.Address(), - }, - } - // Use the same outputs for both C-Chain and P-Chain exports - exportOutputs := []*avax.TransferableOutput{ - { - Asset: avax.Asset{ - ID: avaxAssetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: transferAmount, - OutputOwners: secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - keychain.Keys[0].Address(), - }, - }, - }, - }, - } - - ginkgo.By("sending funds from one address to another on the X-Chain", func() { - _, err = xWallet.IssueBaseTx( - []*avax.TransferableOutput{{ - Asset: avax.Asset{ - ID: avaxAssetID, - }, - Out: &secp256k1fx.TransferOutput{ - Amt: transferAmount, - OutputOwners: recipientOwner, - }, - }}, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { - balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { - _, err := xWallet.IssueExportTx( - cWallet.BlockchainID(), - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("initializing a new eth client") - ethClient := e2e.NewEthClient(nodeURI) - - ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { - _, err := cWallet.IssueImportTx( - xWallet.BlockchainID(), - recipientEthAddress, - e2e.WithDefaultContext(), - e2e.WithSuggestedGasPrice(ethClient), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") - e2e.Eventually(func() bool { - balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) - require.NoError(err) - return balance.Cmp(big.NewInt(0)) > 0 - }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") - - ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { - _, err := xWallet.IssueExportTx( - constants.PlatformChainID, - exportOutputs, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { - _, err := pWallet.IssueImportTx( - xWallet.BlockchainID(), - &recipientOwner, - e2e.WithDefaultContext(), - ) - require.NoError(err) - }) - - ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { - balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( - recipientKey.Address(), - ))) - require.NoError(err) - require.Positive(balances[avaxAssetID]) - }) - - e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) - }) -}) +// import ( +// "math/big" + +// ginkgo "github.com/onsi/ginkgo/v2" + +// "github.com/stretchr/testify/require" + +// "github.com/ava-labs/coreth/plugin/evm" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/tests/e2e" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { +// require := require.New(ginkgo.GinkgoT()) + +// const transferAmount = 10 * units.Avax + +// ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { +// nodeURI := e2e.Env.GetRandomNodeURI() + +// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") +// recipientKey, err := secp256k1.NewPrivateKey() +// require.NoError(err) +// keychain := e2e.Env.NewKeychain(1) +// keychain.Add(recipientKey) +// baseWallet := e2e.NewWallet(keychain, nodeURI) +// xWallet := baseWallet.X() +// cWallet := baseWallet.C() +// pWallet := baseWallet.P() + +// ginkgo.By("defining common configuration") +// recipientEthAddress := evm.GetEthAddress(recipientKey) +// avaxAssetID := xWallet.AVAXAssetID() +// // Use the same owner for sending to X-Chain and importing funds to P-Chain +// recipientOwner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// recipientKey.Address(), +// }, +// } +// // Use the same outputs for both C-Chain and P-Chain exports +// exportOutputs := []*avax.TransferableOutput{ +// { +// Asset: avax.Asset{ +// ID: avaxAssetID, +// }, +// Out: &secp256k1fx.TransferOutput{ +// Amt: transferAmount, +// OutputOwners: secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// keychain.Keys[0].Address(), +// }, +// }, +// }, +// }, +// } + +// ginkgo.By("sending funds from one address to another on the X-Chain", func() { +// _, err = xWallet.IssueBaseTx( +// []*avax.TransferableOutput{{ +// Asset: avax.Asset{ +// ID: avaxAssetID, +// }, +// Out: &secp256k1fx.TransferOutput{ +// Amt: transferAmount, +// OutputOwners: recipientOwner, +// }, +// }}, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { +// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { +// _, err := xWallet.IssueExportTx( +// cWallet.BlockchainID(), +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("initializing a new eth client") +// ethClient := e2e.NewEthClient(nodeURI) + +// ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { +// _, err := cWallet.IssueImportTx( +// xWallet.BlockchainID(), +// recipientEthAddress, +// e2e.WithDefaultContext(), +// e2e.WithSuggestedGasPrice(ethClient), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") +// e2e.Eventually(func() bool { +// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) +// require.NoError(err) +// return balance.Cmp(big.NewInt(0)) > 0 +// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") + +// ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { +// _, err := xWallet.IssueExportTx( +// constants.PlatformChainID, +// exportOutputs, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { +// _, err := pWallet.IssueImportTx( +// xWallet.BlockchainID(), +// &recipientOwner, +// e2e.WithDefaultContext(), +// ) +// require.NoError(err) +// }) + +// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { +// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( +// recipientKey.Address(), +// ))) +// require.NoError(err) +// require.Positive(balances[avaxAssetID]) +// }) + +// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) +// }) +// }) diff --git a/tests/fixture/e2e/helpers.go b/tests/fixture/e2e/helpers.go index 15da611324e0..206da6e41398 100644 --- a/tests/fixture/e2e/helpers.go +++ b/tests/fixture/e2e/helpers.go @@ -16,10 +16,6 @@ import ( "github.com/stretchr/testify/require" - "github.com/ava-labs/coreth/core/types" - "github.com/ava-labs/coreth/ethclient" - "github.com/ava-labs/coreth/interfaces" - "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/tests" "github.com/ava-labs/avalanchego/tests/fixture/testnet" @@ -67,7 +63,7 @@ func NewWallet(keychain *secp256k1fx.Keychain, nodeURI testnet.NodeURI) primary. baseWallet, err := primary.MakeWallet(DefaultContext(), &primary.WalletConfig{ URI: nodeURI.URI, AVAXKeychain: keychain, - EthKeychain: keychain, + // EthKeychain: keychain, }) require.NoError(ginkgo.GinkgoT(), err) return primary.NewWalletWithOptions( @@ -80,15 +76,15 @@ func NewWallet(keychain *secp256k1fx.Keychain, nodeURI testnet.NodeURI) primary. ) } -// Create a new eth client targeting the specified node URI. -func NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { - tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) - nodeAddress := strings.Split(nodeURI.URI, "//")[1] - uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) - client, err := ethclient.Dial(uri) - require.NoError(ginkgo.GinkgoT(), err) - return client -} +// // Create a new eth client targeting the specified node URI. +// func NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { +// tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) +// nodeAddress := strings.Split(nodeURI.URI, "//")[1] +// uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) +// client, err := ethclient.Dial(uri) +// require.NoError(ginkgo.GinkgoT(), err) +// return client +// } // Helper simplifying use of a timed context by canceling the context on ginkgo teardown. func ContextWithTimeout(duration time.Duration) context.Context { @@ -152,49 +148,49 @@ func WaitForHealthy(node testnet.Node) { require.NoError(ginkgo.GinkgoT(), testnet.WaitForHealthy(ctx, node)) } -// Sends an eth transaction, waits for the transaction receipt to be issued -// and checks that the receipt indicates success. -func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { - require := require.New(ginkgo.GinkgoT()) - - txID := signedTx.Hash() - tests.Outf(" sending eth transaction with ID: %s\n", txID) - - require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) - - // Wait for the receipt - var receipt *types.Receipt - Eventually(func() bool { - var err error - receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) - if errors.Is(err, interfaces.NotFound) { - return false // Transaction is still pending - } - require.NoError(err) - return true - }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") - - require.Equal(receipt.Status, types.ReceiptStatusSuccessful) - return receipt -} - -// Determines the suggested gas price for the configured client that will -// maximize the chances of transaction acceptance. -func SuggestGasPrice(ethClient ethclient.Client) *big.Int { - gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) - require.NoError(ginkgo.GinkgoT(), err) - // Double the suggested gas price to maximize the chances of - // acceptance. Maybe this can be revisited pending resolution of - // https://github.com/ava-labs/coreth/issues/314. - gasPrice.Add(gasPrice, gasPrice) - return gasPrice -} - -// Helper simplifying use via an option of a gas price appropriate for testing. -func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { - baseFee := SuggestGasPrice(ethClient) - return common.WithBaseFee(baseFee) -} +// // Sends an eth transaction, waits for the transaction receipt to be issued +// // and checks that the receipt indicates success. +// func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { +// require := require.New(ginkgo.GinkgoT()) + +// txID := signedTx.Hash() +// tests.Outf(" sending eth transaction with ID: %s\n", txID) + +// require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) + +// // Wait for the receipt +// var receipt *types.Receipt +// Eventually(func() bool { +// var err error +// receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) +// if errors.Is(err, interfaces.NotFound) { +// return false // Transaction is still pending +// } +// require.NoError(err) +// return true +// }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") + +// require.Equal(receipt.Status, types.ReceiptStatusSuccessful) +// return receipt +// } + +// // Determines the suggested gas price for the configured client that will +// // maximize the chances of transaction acceptance. +// func SuggestGasPrice(ethClient ethclient.Client) *big.Int { +// gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) +// require.NoError(ginkgo.GinkgoT(), err) +// // Double the suggested gas price to maximize the chances of +// // acceptance. Maybe this can be revisited pending resolution of +// // https://github.com/ava-labs/coreth/issues/314. +// gasPrice.Add(gasPrice, gasPrice) +// return gasPrice +// } + +// // Helper simplifying use via an option of a gas price appropriate for testing. +// func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { +// baseFee := SuggestGasPrice(ethClient) +// return common.WithBaseFee(baseFee) +// } // Verify that a new node can bootstrap into the network. func CheckBootstrapIsPossible(network testnet.Network) { diff --git a/tests/fixture/testnet/config.go b/tests/fixture/testnet/config.go index 425aa646a690..6c82db1a420f 100644 --- a/tests/fixture/testnet/config.go +++ b/tests/fixture/testnet/config.go @@ -15,10 +15,6 @@ import ( "github.com/spf13/cast" - "github.com/ava-labs/coreth/core" - "github.com/ava-labs/coreth/params" - "github.com/ava-labs/coreth/plugin/evm" - "github.com/ava-labs/avalanchego/config" "github.com/ava-labs/avalanchego/genesis" "github.com/ava-labs/avalanchego/ids" @@ -143,15 +139,15 @@ func (c *NetworkConfig) EnsureGenesis(networkID uint32, validatorIDs []ids.NodeI // Ensure pre-funded keys have arbitrary large balances on both chains to support testing xChainBalances := make(XChainBalanceMap, len(c.FundedKeys)) - cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) - for _, key := range c.FundedKeys { - xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount - cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ - Balance: DefaultFundedKeyCChainAmount, - } - } - - genesis, err := NewTestGenesis(networkID, xChainBalances, cChainBalances, validatorIDs) + // cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) + // for _, key := range c.FundedKeys { + // xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount + // cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ + // Balance: DefaultFundedKeyCChainAmount, + // } + // } + + genesis, err := NewTestGenesis(networkID, xChainBalances /*, cChainBalances*/, validatorIDs) if err != nil { return err } @@ -311,7 +307,7 @@ type XChainBalanceMap map[ids.ShortID]uint64 func NewTestGenesis( networkID uint32, xChainBalances XChainBalanceMap, - cChainBalances core.GenesisAlloc, + // cChainBalances core.GenesisAlloc, validatorIDs []ids.NodeID, ) (*genesis.UnparsedConfig, error) { // Validate inputs @@ -322,7 +318,7 @@ func NewTestGenesis( if len(validatorIDs) == 0 { return nil, errMissingValidatorsForGenesis } - if len(xChainBalances) == 0 || len(cChainBalances) == 0 { + if len(xChainBalances) == 0 /*|| len(cChainBalances) == 0*/ { return nil, errMissingBalancesForGenesis } @@ -394,20 +390,20 @@ func NewTestGenesis( ) } - // Define C-Chain genesis - cChainGenesis := &core.Genesis{ - Config: ¶ms.ChainConfig{ - ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary - }, - Difficulty: big.NewInt(0), // Difficulty is a mandatory field - GasLimit: DefaultGasLimit, - Alloc: cChainBalances, - } - cChainGenesisBytes, err := json.Marshal(cChainGenesis) - if err != nil { - return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) - } - config.CChainGenesis = string(cChainGenesisBytes) + // // Define C-Chain genesis + // cChainGenesis := &core.Genesis{ + // Config: ¶ms.ChainConfig{ + // ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary + // }, + // Difficulty: big.NewInt(0), // Difficulty is a mandatory field + // GasLimit: DefaultGasLimit, + // Alloc: cChainBalances, + // } + // cChainGenesisBytes, err := json.Marshal(cChainGenesis) + // if err != nil { + // return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) + // } + // config.CChainGenesis = string(cChainGenesisBytes) // Give staking rewards for initial validators to a random address. Any testing of staking rewards // will be easier to perform with nodes other than the initial validators since the timing of diff --git a/vms/example/xsvm/cmd/chain/create/cmd.go b/vms/example/xsvm/cmd/chain/create/cmd.go index 1f00491a4ce6..043b4298dcdf 100644 --- a/vms/example/xsvm/cmd/chain/create/cmd.go +++ b/vms/example/xsvm/cmd/chain/create/cmd.go @@ -42,9 +42,9 @@ func createFunc(c *cobra.Command, args []string) error { // that [uri] is hosting. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: config.URI, - AVAXKeychain: kc, - EthKeychain: kc, + URI: config.URI, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(config.SubnetID), }) if err != nil { diff --git a/wallet/chain/c/backend.go b/wallet/chain/c/backend.go index 0a735116b646..b88c8c643bc3 100644 --- a/wallet/chain/c/backend.go +++ b/wallet/chain/c/backend.go @@ -3,153 +3,153 @@ package c -import ( - "errors" - "fmt" - "math/big" - "sync" - - stdcontext "context" - - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/utils/math" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var ( - _ Backend = (*backend)(nil) - - errUnknownTxType = errors.New("unknown tx type") -) - -// Backend defines the full interface required to support a C-chain wallet. -type Backend interface { - common.ChainUTXOs - BuilderBackend - SignerBackend - - AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error -} - -type backend struct { - Context - common.ChainUTXOs - - accountsLock sync.RWMutex - accounts map[ethcommon.Address]*Account -} - -type Account struct { - Balance *big.Int - Nonce uint64 -} - -func NewBackend( - ctx Context, - utxos common.ChainUTXOs, - accounts map[ethcommon.Address]*Account, -) Backend { - return &backend{ - Context: ctx, - ChainUTXOs: utxos, - accounts: accounts, - } -} - -func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { - switch tx := tx.UnsignedAtomicTx.(type) { - case *evm.UnsignedImportTx: - for _, input := range tx.ImportedInputs { - utxoID := input.InputID() - if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { - return err - } - } - - b.accountsLock.Lock() - defer b.accountsLock.Unlock() - - for _, output := range tx.Outs { - account, ok := b.accounts[output.Address] - if !ok { - continue - } - - balance := new(big.Int).SetUint64(output.Amount) - balance.Mul(balance, avaxConversionRate) - account.Balance.Add(account.Balance, balance) - } - case *evm.UnsignedExportTx: - txID := tx.ID() - for i, out := range tx.ExportedOutputs { - err := b.AddUTXO( - ctx, - tx.DestinationChain, - &avax.UTXO{ - UTXOID: avax.UTXOID{ - TxID: txID, - OutputIndex: uint32(i), - }, - Asset: avax.Asset{ID: out.AssetID()}, - Out: out.Out, - }, - ) - if err != nil { - return err - } - } - - b.accountsLock.Lock() - defer b.accountsLock.Unlock() - - for _, input := range tx.Ins { - account, ok := b.accounts[input.Address] - if !ok { - continue - } - - balance := new(big.Int).SetUint64(input.Amount) - balance.Mul(balance, avaxConversionRate) - if account.Balance.Cmp(balance) == -1 { - return errInsufficientFunds - } - account.Balance.Sub(account.Balance, balance) - - newNonce, err := math.Add64(input.Nonce, 1) - if err != nil { - return err - } - account.Nonce = newNonce - } - default: - return fmt.Errorf("%w: %T", errUnknownTxType, tx) - } - return nil -} - -func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { - b.accountsLock.RLock() - defer b.accountsLock.RUnlock() - - account, exists := b.accounts[addr] - if !exists { - return nil, database.ErrNotFound - } - return account.Balance, nil -} - -func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { - b.accountsLock.RLock() - defer b.accountsLock.RUnlock() - - account, exists := b.accounts[addr] - if !exists { - return 0, database.ErrNotFound - } - return account.Nonce, nil -} +// import ( +// "errors" +// "fmt" +// "math/big" +// "sync" + +// stdcontext "context" + +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/database" +// "github.com/ava-labs/avalanchego/utils/math" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var ( +// _ Backend = (*backend)(nil) + +// errUnknownTxType = errors.New("unknown tx type") +// ) + +// // Backend defines the full interface required to support a C-chain wallet. +// type Backend interface { +// common.ChainUTXOs +// BuilderBackend +// SignerBackend + +// AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error +// } + +// type backend struct { +// Context +// common.ChainUTXOs + +// accountsLock sync.RWMutex +// accounts map[ethcommon.Address]*Account +// } + +// type Account struct { +// Balance *big.Int +// Nonce uint64 +// } + +// func NewBackend( +// ctx Context, +// utxos common.ChainUTXOs, +// accounts map[ethcommon.Address]*Account, +// ) Backend { +// return &backend{ +// Context: ctx, +// ChainUTXOs: utxos, +// accounts: accounts, +// } +// } + +// func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { +// switch tx := tx.UnsignedAtomicTx.(type) { +// case *evm.UnsignedImportTx: +// for _, input := range tx.ImportedInputs { +// utxoID := input.InputID() +// if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { +// return err +// } +// } + +// b.accountsLock.Lock() +// defer b.accountsLock.Unlock() + +// for _, output := range tx.Outs { +// account, ok := b.accounts[output.Address] +// if !ok { +// continue +// } + +// balance := new(big.Int).SetUint64(output.Amount) +// balance.Mul(balance, avaxConversionRate) +// account.Balance.Add(account.Balance, balance) +// } +// case *evm.UnsignedExportTx: +// txID := tx.ID() +// for i, out := range tx.ExportedOutputs { +// err := b.AddUTXO( +// ctx, +// tx.DestinationChain, +// &avax.UTXO{ +// UTXOID: avax.UTXOID{ +// TxID: txID, +// OutputIndex: uint32(i), +// }, +// Asset: avax.Asset{ID: out.AssetID()}, +// Out: out.Out, +// }, +// ) +// if err != nil { +// return err +// } +// } + +// b.accountsLock.Lock() +// defer b.accountsLock.Unlock() + +// for _, input := range tx.Ins { +// account, ok := b.accounts[input.Address] +// if !ok { +// continue +// } + +// balance := new(big.Int).SetUint64(input.Amount) +// balance.Mul(balance, avaxConversionRate) +// if account.Balance.Cmp(balance) == -1 { +// return errInsufficientFunds +// } +// account.Balance.Sub(account.Balance, balance) + +// newNonce, err := math.Add64(input.Nonce, 1) +// if err != nil { +// return err +// } +// account.Nonce = newNonce +// } +// default: +// return fmt.Errorf("%w: %T", errUnknownTxType, tx) +// } +// return nil +// } + +// func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { +// b.accountsLock.RLock() +// defer b.accountsLock.RUnlock() + +// account, exists := b.accounts[addr] +// if !exists { +// return nil, database.ErrNotFound +// } +// return account.Balance, nil +// } + +// func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { +// b.accountsLock.RLock() +// defer b.accountsLock.RUnlock() + +// account, exists := b.accounts[addr] +// if !exists { +// return 0, database.ErrNotFound +// } +// return account.Nonce, nil +// } diff --git a/wallet/chain/c/builder.go b/wallet/chain/c/builder.go index d2d088e88a53..c51d2647777e 100644 --- a/wallet/chain/c/builder.go +++ b/wallet/chain/c/builder.go @@ -3,399 +3,399 @@ package c -import ( - "errors" - "math/big" - - stdcontext "context" - - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils" - "github.com/ava-labs/avalanchego/utils/math" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -const avaxConversionRateInt = 1_000_000_000 - -var ( - _ Builder = (*builder)(nil) - - errInsufficientFunds = errors.New("insufficient funds") - - // avaxConversionRate is the conversion rate between the smallest - // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest - // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. - // - // This is only required for AVAX because the denomination of 1 AVAX is 9 - // decimal places on the X and P chains, but is 18 decimal places within the - // EVM. - avaxConversionRate = big.NewInt(avaxConversionRateInt) -) - -// Builder provides a convenient interface for building unsigned C-chain -// transactions. -type Builder interface { - // GetBalance calculates the amount of AVAX that this builder has control - // over. - GetBalance( - options ...common.Option, - ) (*big.Int, error) - - // GetImportableBalance calculates the amount of AVAX that this builder - // could import from the provided chain. - // - // - [chainID] specifies the chain the funds are from. - GetImportableBalance( - chainID ids.ID, - options ...common.Option, - ) (uint64, error) - - // NewImportTx creates an import transaction that attempts to consume all - // the available UTXOs and import the funds to [to]. - // - // - [chainID] specifies the chain to be importing funds from. - // - [to] specifies where to send the imported funds to. - // - [baseFee] specifies the fee price willing to be paid by this tx. - NewImportTx( - chainID ids.ID, - to ethcommon.Address, - baseFee *big.Int, - options ...common.Option, - ) (*evm.UnsignedImportTx, error) - - // NewExportTx creates an export transaction that attempts to send all the - // provided [outputs] to the requested [chainID]. - // - // - [chainID] specifies the chain to be exporting the funds to. - // - [outputs] specifies the outputs to send to the [chainID]. - // - [baseFee] specifies the fee price willing to be paid by this tx. - NewExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - baseFee *big.Int, - options ...common.Option, - ) (*evm.UnsignedExportTx, error) -} - -// BuilderBackend specifies the required information needed to build unsigned -// C-chain transactions. -type BuilderBackend interface { - Context - - UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) - Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) - Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) -} - -type builder struct { - avaxAddrs set.Set[ids.ShortID] - ethAddrs set.Set[ethcommon.Address] - backend BuilderBackend -} - -// NewBuilder returns a new transaction builder. -// -// - [avaxAddrs] is the set of addresses in the AVAX format that the builder -// assumes can be used when signing the transactions in the future. -// - [ethAddrs] is the set of addresses in the Eth format that the builder -// assumes can be used when signing the transactions in the future. -// - [backend] provides the required access to the chain's context and state -// to build out the transactions. -func NewBuilder( - avaxAddrs set.Set[ids.ShortID], - ethAddrs set.Set[ethcommon.Address], - backend BuilderBackend, -) Builder { - return &builder{ - avaxAddrs: avaxAddrs, - ethAddrs: ethAddrs, - backend: backend, - } -} - -func (b *builder) GetBalance( - options ...common.Option, -) (*big.Int, error) { - var ( - ops = common.NewOptions(options) - ctx = ops.Context() - addrs = ops.EthAddresses(b.ethAddrs) - totalBalance = new(big.Int) - ) - for addr := range addrs { - balance, err := b.backend.Balance(ctx, addr) - if err != nil { - return nil, err - } - totalBalance.Add(totalBalance, balance) - } - - return totalBalance, nil -} - -func (b *builder) GetImportableBalance( - chainID ids.ID, - options ...common.Option, -) (uint64, error) { - ops := common.NewOptions(options) - utxos, err := b.backend.UTXOs(ops.Context(), chainID) - if err != nil { - return 0, err - } - - var ( - addrs = ops.Addresses(b.avaxAddrs) - minIssuanceTime = ops.MinIssuanceTime() - avaxAssetID = b.backend.AVAXAssetID() - balance uint64 - ) - for _, utxo := range utxos { - amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) - if !ok { - continue - } - - newBalance, err := math.Add64(balance, amount) - if err != nil { - return 0, err - } - balance = newBalance - } - - return balance, nil -} - -func (b *builder) NewImportTx( - chainID ids.ID, - to ethcommon.Address, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedImportTx, error) { - ops := common.NewOptions(options) - utxos, err := b.backend.UTXOs(ops.Context(), chainID) - if err != nil { - return nil, err - } - - var ( - addrs = ops.Addresses(b.avaxAddrs) - minIssuanceTime = ops.MinIssuanceTime() - avaxAssetID = b.backend.AVAXAssetID() - - importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) - importedAmount uint64 - ) - for _, utxo := range utxos { - amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) - if !ok { - continue - } - - importedInputs = append(importedInputs, &avax.TransferableInput{ - UTXOID: utxo.UTXOID, - Asset: utxo.Asset, - In: &secp256k1fx.TransferInput{ - Amt: amount, - Input: secp256k1fx.Input{ - SigIndices: inputSigIndices, - }, - }, - }) - - newImportedAmount, err := math.Add64(importedAmount, amount) - if err != nil { - return nil, err - } - importedAmount = newImportedAmount - } - - utils.Sort(importedInputs) - tx := &evm.UnsignedImportTx{ - NetworkID: b.backend.NetworkID(), - BlockchainID: b.backend.BlockchainID(), - SourceChain: chainID, - ImportedInputs: importedInputs, - } - - // We must initialize the bytes of the tx to calculate the initial cost - wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} - if err := wrappedTx.Sign(evm.Codec, nil); err != nil { - return nil, err - } - - gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) - if err != nil { - return nil, err - } - gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas - - txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) - if err != nil { - return nil, err - } - - if importedAmount <= txFee { - return nil, errInsufficientFunds - } - - tx.Outs = []evm.EVMOutput{{ - Address: to, - Amount: importedAmount - txFee, - AssetID: avaxAssetID, - }} - return tx, nil -} - -func (b *builder) NewExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedExportTx, error) { - var ( - avaxAssetID = b.backend.AVAXAssetID() - exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) - exportedAmount uint64 - ) - for i, output := range outputs { - exportedOutputs[i] = &avax.TransferableOutput{ - Asset: avax.Asset{ID: avaxAssetID}, - Out: output, - } - - newExportedAmount, err := math.Add64(exportedAmount, output.Amt) - if err != nil { - return nil, err - } - exportedAmount = newExportedAmount - } - - avax.SortTransferableOutputs(exportedOutputs, evm.Codec) - tx := &evm.UnsignedExportTx{ - NetworkID: b.backend.NetworkID(), - BlockchainID: b.backend.BlockchainID(), - DestinationChain: chainID, - ExportedOutputs: exportedOutputs, - } - - // We must initialize the bytes of the tx to calculate the initial cost - wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} - if err := wrappedTx.Sign(evm.Codec, nil); err != nil { - return nil, err - } - - cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) - if err != nil { - return nil, err - } - - initialFee, err := evm.CalculateDynamicFee(cost, baseFee) - if err != nil { - return nil, err - } - - amountToConsume, err := math.Add64(exportedAmount, initialFee) - if err != nil { - return nil, err - } - - var ( - ops = common.NewOptions(options) - ctx = ops.Context() - addrs = ops.EthAddresses(b.ethAddrs) - inputs = make([]evm.EVMInput, 0, addrs.Len()) - ) - for addr := range addrs { - if amountToConsume == 0 { - break - } - - prevFee, err := evm.CalculateDynamicFee(cost, baseFee) - if err != nil { - return nil, err - } - - newCost := cost + evm.EVMInputGas - newFee, err := evm.CalculateDynamicFee(newCost, baseFee) - if err != nil { - return nil, err - } - - additionalFee := newFee - prevFee - - balance, err := b.backend.Balance(ctx, addr) - if err != nil { - return nil, err - } - - // Since the asset is AVAX, we divide by the avaxConversionRate to - // convert back to the correct denomination of AVAX that can be - // exported. - avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() - - // If the balance for [addr] is insufficient to cover the additional - // cost of adding an input to the transaction, skip adding the input - // altogether. - if avaxBalance <= additionalFee { - continue - } - - // Update the cost for the next iteration - cost = newCost - - amountToConsume, err = math.Add64(amountToConsume, additionalFee) - if err != nil { - return nil, err - } - - nonce, err := b.backend.Nonce(ctx, addr) - if err != nil { - return nil, err - } - - inputAmount := math.Min(amountToConsume, avaxBalance) - inputs = append(inputs, evm.EVMInput{ - Address: addr, - Amount: inputAmount, - AssetID: avaxAssetID, - Nonce: nonce, - }) - amountToConsume -= inputAmount - } - - if amountToConsume > 0 { - return nil, errInsufficientFunds - } - - utils.Sort(inputs) - tx.Ins = inputs - return tx, nil -} - -func getSpendableAmount( - utxo *avax.UTXO, - addrs set.Set[ids.ShortID], - minIssuanceTime uint64, - avaxAssetID ids.ID, -) (uint64, []uint32, bool) { - if utxo.Asset.ID != avaxAssetID { - // Only AVAX can be imported - return 0, nil, false - } - - out, ok := utxo.Out.(*secp256k1fx.TransferOutput) - if !ok { - // Can't import an unknown transfer output type - return 0, nil, false - } - - inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) - return out.Amt, inputSigIndices, ok -} +// import ( +// "errors" +// "math/big" + +// stdcontext "context" + +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils" +// "github.com/ava-labs/avalanchego/utils/math" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// const avaxConversionRateInt = 1_000_000_000 + +// var ( +// _ Builder = (*builder)(nil) + +// errInsufficientFunds = errors.New("insufficient funds") + +// // avaxConversionRate is the conversion rate between the smallest +// // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest +// // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. +// // +// // This is only required for AVAX because the denomination of 1 AVAX is 9 +// // decimal places on the X and P chains, but is 18 decimal places within the +// // EVM. +// avaxConversionRate = big.NewInt(avaxConversionRateInt) +// ) + +// // Builder provides a convenient interface for building unsigned C-chain +// // transactions. +// type Builder interface { +// // GetBalance calculates the amount of AVAX that this builder has control +// // over. +// GetBalance( +// options ...common.Option, +// ) (*big.Int, error) + +// // GetImportableBalance calculates the amount of AVAX that this builder +// // could import from the provided chain. +// // +// // - [chainID] specifies the chain the funds are from. +// GetImportableBalance( +// chainID ids.ID, +// options ...common.Option, +// ) (uint64, error) + +// // NewImportTx creates an import transaction that attempts to consume all +// // the available UTXOs and import the funds to [to]. +// // +// // - [chainID] specifies the chain to be importing funds from. +// // - [to] specifies where to send the imported funds to. +// // - [baseFee] specifies the fee price willing to be paid by this tx. +// NewImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedImportTx, error) + +// // NewExportTx creates an export transaction that attempts to send all the +// // provided [outputs] to the requested [chainID]. +// // +// // - [chainID] specifies the chain to be exporting the funds to. +// // - [outputs] specifies the outputs to send to the [chainID]. +// // - [baseFee] specifies the fee price willing to be paid by this tx. +// NewExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedExportTx, error) +// } + +// // BuilderBackend specifies the required information needed to build unsigned +// // C-chain transactions. +// type BuilderBackend interface { +// Context + +// UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) +// Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) +// Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) +// } + +// type builder struct { +// avaxAddrs set.Set[ids.ShortID] +// ethAddrs set.Set[ethcommon.Address] +// backend BuilderBackend +// } + +// // NewBuilder returns a new transaction builder. +// // +// // - [avaxAddrs] is the set of addresses in the AVAX format that the builder +// // assumes can be used when signing the transactions in the future. +// // - [ethAddrs] is the set of addresses in the Eth format that the builder +// // assumes can be used when signing the transactions in the future. +// // - [backend] provides the required access to the chain's context and state +// // to build out the transactions. +// func NewBuilder( +// avaxAddrs set.Set[ids.ShortID], +// ethAddrs set.Set[ethcommon.Address], +// backend BuilderBackend, +// ) Builder { +// return &builder{ +// avaxAddrs: avaxAddrs, +// ethAddrs: ethAddrs, +// backend: backend, +// } +// } + +// func (b *builder) GetBalance( +// options ...common.Option, +// ) (*big.Int, error) { +// var ( +// ops = common.NewOptions(options) +// ctx = ops.Context() +// addrs = ops.EthAddresses(b.ethAddrs) +// totalBalance = new(big.Int) +// ) +// for addr := range addrs { +// balance, err := b.backend.Balance(ctx, addr) +// if err != nil { +// return nil, err +// } +// totalBalance.Add(totalBalance, balance) +// } + +// return totalBalance, nil +// } + +// func (b *builder) GetImportableBalance( +// chainID ids.ID, +// options ...common.Option, +// ) (uint64, error) { +// ops := common.NewOptions(options) +// utxos, err := b.backend.UTXOs(ops.Context(), chainID) +// if err != nil { +// return 0, err +// } + +// var ( +// addrs = ops.Addresses(b.avaxAddrs) +// minIssuanceTime = ops.MinIssuanceTime() +// avaxAssetID = b.backend.AVAXAssetID() +// balance uint64 +// ) +// for _, utxo := range utxos { +// amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) +// if !ok { +// continue +// } + +// newBalance, err := math.Add64(balance, amount) +// if err != nil { +// return 0, err +// } +// balance = newBalance +// } + +// return balance, nil +// } + +// func (b *builder) NewImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedImportTx, error) { +// ops := common.NewOptions(options) +// utxos, err := b.backend.UTXOs(ops.Context(), chainID) +// if err != nil { +// return nil, err +// } + +// var ( +// addrs = ops.Addresses(b.avaxAddrs) +// minIssuanceTime = ops.MinIssuanceTime() +// avaxAssetID = b.backend.AVAXAssetID() + +// importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) +// importedAmount uint64 +// ) +// for _, utxo := range utxos { +// amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) +// if !ok { +// continue +// } + +// importedInputs = append(importedInputs, &avax.TransferableInput{ +// UTXOID: utxo.UTXOID, +// Asset: utxo.Asset, +// In: &secp256k1fx.TransferInput{ +// Amt: amount, +// Input: secp256k1fx.Input{ +// SigIndices: inputSigIndices, +// }, +// }, +// }) + +// newImportedAmount, err := math.Add64(importedAmount, amount) +// if err != nil { +// return nil, err +// } +// importedAmount = newImportedAmount +// } + +// utils.Sort(importedInputs) +// tx := &evm.UnsignedImportTx{ +// NetworkID: b.backend.NetworkID(), +// BlockchainID: b.backend.BlockchainID(), +// SourceChain: chainID, +// ImportedInputs: importedInputs, +// } + +// // We must initialize the bytes of the tx to calculate the initial cost +// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} +// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { +// return nil, err +// } + +// gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) +// if err != nil { +// return nil, err +// } +// gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas + +// txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) +// if err != nil { +// return nil, err +// } + +// if importedAmount <= txFee { +// return nil, errInsufficientFunds +// } + +// tx.Outs = []evm.EVMOutput{{ +// Address: to, +// Amount: importedAmount - txFee, +// AssetID: avaxAssetID, +// }} +// return tx, nil +// } + +// func (b *builder) NewExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedExportTx, error) { +// var ( +// avaxAssetID = b.backend.AVAXAssetID() +// exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) +// exportedAmount uint64 +// ) +// for i, output := range outputs { +// exportedOutputs[i] = &avax.TransferableOutput{ +// Asset: avax.Asset{ID: avaxAssetID}, +// Out: output, +// } + +// newExportedAmount, err := math.Add64(exportedAmount, output.Amt) +// if err != nil { +// return nil, err +// } +// exportedAmount = newExportedAmount +// } + +// avax.SortTransferableOutputs(exportedOutputs, evm.Codec) +// tx := &evm.UnsignedExportTx{ +// NetworkID: b.backend.NetworkID(), +// BlockchainID: b.backend.BlockchainID(), +// DestinationChain: chainID, +// ExportedOutputs: exportedOutputs, +// } + +// // We must initialize the bytes of the tx to calculate the initial cost +// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} +// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { +// return nil, err +// } + +// cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) +// if err != nil { +// return nil, err +// } + +// initialFee, err := evm.CalculateDynamicFee(cost, baseFee) +// if err != nil { +// return nil, err +// } + +// amountToConsume, err := math.Add64(exportedAmount, initialFee) +// if err != nil { +// return nil, err +// } + +// var ( +// ops = common.NewOptions(options) +// ctx = ops.Context() +// addrs = ops.EthAddresses(b.ethAddrs) +// inputs = make([]evm.EVMInput, 0, addrs.Len()) +// ) +// for addr := range addrs { +// if amountToConsume == 0 { +// break +// } + +// prevFee, err := evm.CalculateDynamicFee(cost, baseFee) +// if err != nil { +// return nil, err +// } + +// newCost := cost + evm.EVMInputGas +// newFee, err := evm.CalculateDynamicFee(newCost, baseFee) +// if err != nil { +// return nil, err +// } + +// additionalFee := newFee - prevFee + +// balance, err := b.backend.Balance(ctx, addr) +// if err != nil { +// return nil, err +// } + +// // Since the asset is AVAX, we divide by the avaxConversionRate to +// // convert back to the correct denomination of AVAX that can be +// // exported. +// avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() + +// // If the balance for [addr] is insufficient to cover the additional +// // cost of adding an input to the transaction, skip adding the input +// // altogether. +// if avaxBalance <= additionalFee { +// continue +// } + +// // Update the cost for the next iteration +// cost = newCost + +// amountToConsume, err = math.Add64(amountToConsume, additionalFee) +// if err != nil { +// return nil, err +// } + +// nonce, err := b.backend.Nonce(ctx, addr) +// if err != nil { +// return nil, err +// } + +// inputAmount := math.Min(amountToConsume, avaxBalance) +// inputs = append(inputs, evm.EVMInput{ +// Address: addr, +// Amount: inputAmount, +// AssetID: avaxAssetID, +// Nonce: nonce, +// }) +// amountToConsume -= inputAmount +// } + +// if amountToConsume > 0 { +// return nil, errInsufficientFunds +// } + +// utils.Sort(inputs) +// tx.Ins = inputs +// return tx, nil +// } + +// func getSpendableAmount( +// utxo *avax.UTXO, +// addrs set.Set[ids.ShortID], +// minIssuanceTime uint64, +// avaxAssetID ids.ID, +// ) (uint64, []uint32, bool) { +// if utxo.Asset.ID != avaxAssetID { +// // Only AVAX can be imported +// return 0, nil, false +// } + +// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) +// if !ok { +// // Can't import an unknown transfer output type +// return 0, nil, false +// } + +// inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) +// return out.Amt, inputSigIndices, ok +// } diff --git a/wallet/chain/c/builder_with_options.go b/wallet/chain/c/builder_with_options.go index 8416dddf9928..9b7ab8399484 100644 --- a/wallet/chain/c/builder_with_options.go +++ b/wallet/chain/c/builder_with_options.go @@ -3,81 +3,81 @@ package c -import ( - "math/big" +// import ( +// "math/big" - "github.com/ava-labs/coreth/plugin/evm" +// "github.com/ava-labs/coreth/plugin/evm" - ethcommon "github.com/ethereum/go-ethereum/common" +// ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) -var _ Builder = (*builderWithOptions)(nil) +// var _ Builder = (*builderWithOptions)(nil) -type builderWithOptions struct { - Builder - options []common.Option -} +// type builderWithOptions struct { +// Builder +// options []common.Option +// } -// NewBuilderWithOptions returns a new transaction builder that will use the -// given options by default. -// -// - [builder] is the builder that will be called to perform the underlying -// operations. -// - [options] will be provided to the builder in addition to the options -// provided in the method calls. -func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { - return &builderWithOptions{ - Builder: builder, - options: options, - } -} +// // NewBuilderWithOptions returns a new transaction builder that will use the +// // given options by default. +// // +// // - [builder] is the builder that will be called to perform the underlying +// // operations. +// // - [options] will be provided to the builder in addition to the options +// // provided in the method calls. +// func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { +// return &builderWithOptions{ +// Builder: builder, +// options: options, +// } +// } -func (b *builderWithOptions) GetBalance( - options ...common.Option, -) (*big.Int, error) { - return b.Builder.GetBalance( - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) GetBalance( +// options ...common.Option, +// ) (*big.Int, error) { +// return b.Builder.GetBalance( +// common.UnionOptions(b.options, options)..., +// ) +// } -func (b *builderWithOptions) GetImportableBalance( - chainID ids.ID, - options ...common.Option, -) (uint64, error) { - return b.Builder.GetImportableBalance( - chainID, - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) GetImportableBalance( +// chainID ids.ID, +// options ...common.Option, +// ) (uint64, error) { +// return b.Builder.GetImportableBalance( +// chainID, +// common.UnionOptions(b.options, options)..., +// ) +// } -func (b *builderWithOptions) NewImportTx( - chainID ids.ID, - to ethcommon.Address, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedImportTx, error) { - return b.Builder.NewImportTx( - chainID, - to, - baseFee, - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) NewImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedImportTx, error) { +// return b.Builder.NewImportTx( +// chainID, +// to, +// baseFee, +// common.UnionOptions(b.options, options)..., +// ) +// } -func (b *builderWithOptions) NewExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - baseFee *big.Int, - options ...common.Option, -) (*evm.UnsignedExportTx, error) { - return b.Builder.NewExportTx( - chainID, - outputs, - baseFee, - common.UnionOptions(b.options, options)..., - ) -} +// func (b *builderWithOptions) NewExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// baseFee *big.Int, +// options ...common.Option, +// ) (*evm.UnsignedExportTx, error) { +// return b.Builder.NewExportTx( +// chainID, +// outputs, +// baseFee, +// common.UnionOptions(b.options, options)..., +// ) +// } diff --git a/wallet/chain/c/context.go b/wallet/chain/c/context.go index d506b42f81fa..1c01d8fb55c8 100644 --- a/wallet/chain/c/context.go +++ b/wallet/chain/c/context.go @@ -3,81 +3,81 @@ package c -import ( - stdcontext "context" +// import ( +// stdcontext "context" - "github.com/ava-labs/avalanchego/api/info" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/avm" -) +// "github.com/ava-labs/avalanchego/api/info" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/avm" +// ) -var _ Context = (*context)(nil) +// var _ Context = (*context)(nil) -type Context interface { - NetworkID() uint32 - BlockchainID() ids.ID - AVAXAssetID() ids.ID -} +// type Context interface { +// NetworkID() uint32 +// BlockchainID() ids.ID +// AVAXAssetID() ids.ID +// } -type context struct { - networkID uint32 - blockchainID ids.ID - avaxAssetID ids.ID -} +// type context struct { +// networkID uint32 +// blockchainID ids.ID +// avaxAssetID ids.ID +// } -func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { - infoClient := info.NewClient(uri) - xChainClient := avm.NewClient(uri, "X") - return NewContextFromClients(ctx, infoClient, xChainClient) -} +// func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { +// infoClient := info.NewClient(uri) +// xChainClient := avm.NewClient(uri, "X") +// return NewContextFromClients(ctx, infoClient, xChainClient) +// } -func NewContextFromClients( - ctx stdcontext.Context, - infoClient info.Client, - xChainClient avm.Client, -) (Context, error) { - networkID, err := infoClient.GetNetworkID(ctx) - if err != nil { - return nil, err - } +// func NewContextFromClients( +// ctx stdcontext.Context, +// infoClient info.Client, +// xChainClient avm.Client, +// ) (Context, error) { +// networkID, err := infoClient.GetNetworkID(ctx) +// if err != nil { +// return nil, err +// } - chainID, err := infoClient.GetBlockchainID(ctx, "C") - if err != nil { - return nil, err - } +// chainID, err := infoClient.GetBlockchainID(ctx, "C") +// if err != nil { +// return nil, err +// } - asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") - if err != nil { - return nil, err - } +// asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") +// if err != nil { +// return nil, err +// } - return NewContext( - networkID, - chainID, - asset.AssetID, - ), nil -} +// return NewContext( +// networkID, +// chainID, +// asset.AssetID, +// ), nil +// } -func NewContext( - networkID uint32, - blockchainID ids.ID, - avaxAssetID ids.ID, -) Context { - return &context{ - networkID: networkID, - blockchainID: blockchainID, - avaxAssetID: avaxAssetID, - } -} +// func NewContext( +// networkID uint32, +// blockchainID ids.ID, +// avaxAssetID ids.ID, +// ) Context { +// return &context{ +// networkID: networkID, +// blockchainID: blockchainID, +// avaxAssetID: avaxAssetID, +// } +// } -func (c *context) NetworkID() uint32 { - return c.networkID -} +// func (c *context) NetworkID() uint32 { +// return c.networkID +// } -func (c *context) BlockchainID() ids.ID { - return c.blockchainID -} +// func (c *context) BlockchainID() ids.ID { +// return c.blockchainID +// } -func (c *context) AVAXAssetID() ids.ID { - return c.avaxAssetID -} +// func (c *context) AVAXAssetID() ids.ID { +// return c.avaxAssetID +// } diff --git a/wallet/chain/c/signer.go b/wallet/chain/c/signer.go index 4fd85ed3b532..4bedc378234b 100644 --- a/wallet/chain/c/signer.go +++ b/wallet/chain/c/signer.go @@ -3,221 +3,221 @@ package c -import ( - "errors" - "fmt" - - stdcontext "context" - - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/crypto/keychain" - "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" - "github.com/ava-labs/avalanchego/utils/hashing" - "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/components/verify" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" -) - -const version = 0 - -var ( - _ Signer = (*txSigner)(nil) - - errUnknownInputType = errors.New("unknown input type") - errUnknownCredentialType = errors.New("unknown credential type") - errUnknownOutputType = errors.New("unknown output type") - errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") - - emptySig [secp256k1.SignatureLen]byte -) - -type Signer interface { - SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) - SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error -} - -type EthKeychain interface { - // The returned Signer can provide a signature for [addr] - GetEth(addr ethcommon.Address) (keychain.Signer, bool) - // Returns the set of addresses for which the accessor keeps an associated - // signer - EthAddresses() set.Set[ethcommon.Address] -} - -type SignerBackend interface { - GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) -} - -type txSigner struct { - avaxKC keychain.Keychain - ethKC EthKeychain - backend SignerBackend -} - -func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { - return &txSigner{ - avaxKC: avaxKC, - ethKC: ethKC, - backend: backend, - } -} - -func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { - tx := &evm.Tx{UnsignedAtomicTx: utx} - return tx, s.SignAtomic(ctx, tx) -} - -func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { - switch utx := tx.UnsignedAtomicTx.(type) { - case *evm.UnsignedImportTx: - signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) - if err != nil { - return err - } - return sign(tx, true, signers) - case *evm.UnsignedExportTx: - signers := s.getExportSigners(utx.Ins) - return sign(tx, true, signers) - default: - return fmt.Errorf("%w: %T", errUnknownTxType, tx) - } -} - -func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { - txSigners := make([][]keychain.Signer, len(ins)) - for credIndex, transferInput := range ins { - input, ok := transferInput.In.(*secp256k1fx.TransferInput) - if !ok { - return nil, errUnknownInputType - } - - inputSigners := make([]keychain.Signer, len(input.SigIndices)) - txSigners[credIndex] = inputSigners - - utxoID := transferInput.InputID() - utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) - if err == database.ErrNotFound { - // If we don't have access to the UTXO, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - if err != nil { - return nil, err - } - - out, ok := utxo.Out.(*secp256k1fx.TransferOutput) - if !ok { - return nil, errUnknownOutputType - } - - for sigIndex, addrIndex := range input.SigIndices { - if addrIndex >= uint32(len(out.Addrs)) { - return nil, errInvalidUTXOSigIndex - } - - addr := out.Addrs[addrIndex] - key, ok := s.avaxKC.Get(addr) - if !ok { - // If we don't have access to the key, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - inputSigners[sigIndex] = key - } - } - return txSigners, nil -} - -func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { - txSigners := make([][]keychain.Signer, len(ins)) - for credIndex, input := range ins { - inputSigners := make([]keychain.Signer, 1) - txSigners[credIndex] = inputSigners - - key, ok := s.ethKC.GetEth(input.Address) - if !ok { - // If we don't have access to the key, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - inputSigners[0] = key - } - return txSigners -} - -// TODO: remove [signHash] after the ledger supports signing all transactions. -func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { - unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) - if err != nil { - return fmt.Errorf("couldn't marshal unsigned tx: %w", err) - } - unsignedHash := hashing.ComputeHash256(unsignedBytes) - - if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { - tx.Creds = make([]verify.Verifiable, expectedLen) - } - - sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) - for credIndex, inputSigners := range txSigners { - credIntf := tx.Creds[credIndex] - if credIntf == nil { - credIntf = &secp256k1fx.Credential{} - tx.Creds[credIndex] = credIntf - } - - cred, ok := credIntf.(*secp256k1fx.Credential) - if !ok { - return errUnknownCredentialType - } - if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { - cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) - } - - for sigIndex, signer := range inputSigners { - if signer == nil { - // If we don't have access to the key, then we can't sign this - // transaction. However, we can attempt to partially sign it. - continue - } - addr := signer.Address() - if sig := cred.Sigs[sigIndex]; sig != emptySig { - // If this signature has already been populated, we can just - // copy the needed signature for the future. - sigCache[addr] = sig - continue - } - - if sig, exists := sigCache[addr]; exists { - // If this key has already produced a signature, we can just - // copy the previous signature. - cred.Sigs[sigIndex] = sig - continue - } - - var sig []byte - if signHash { - sig, err = signer.SignHash(unsignedHash) - } else { - sig, err = signer.Sign(unsignedBytes) - } - if err != nil { - return fmt.Errorf("problem signing tx: %w", err) - } - copy(cred.Sigs[sigIndex][:], sig) - sigCache[addr] = cred.Sigs[sigIndex] - } - } - - signedBytes, err := evm.Codec.Marshal(version, tx) - if err != nil { - return fmt.Errorf("couldn't marshal tx: %w", err) - } - tx.Initialize(unsignedBytes, signedBytes) - return nil -} +// import ( +// "errors" +// "fmt" + +// stdcontext "context" + +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/database" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils/crypto/keychain" +// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +// "github.com/ava-labs/avalanchego/utils/hashing" +// "github.com/ava-labs/avalanchego/utils/set" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/components/verify" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// ) + +// const version = 0 + +// var ( +// _ Signer = (*txSigner)(nil) + +// errUnknownInputType = errors.New("unknown input type") +// errUnknownCredentialType = errors.New("unknown credential type") +// errUnknownOutputType = errors.New("unknown output type") +// errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") + +// emptySig [secp256k1.SignatureLen]byte +// ) + +// type Signer interface { +// SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) +// SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error +// } + +// type EthKeychain interface { +// // The returned Signer can provide a signature for [addr] +// GetEth(addr ethcommon.Address) (keychain.Signer, bool) +// // Returns the set of addresses for which the accessor keeps an associated +// // signer +// EthAddresses() set.Set[ethcommon.Address] +// } + +// type SignerBackend interface { +// GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) +// } + +// type txSigner struct { +// avaxKC keychain.Keychain +// ethKC EthKeychain +// backend SignerBackend +// } + +// func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { +// return &txSigner{ +// avaxKC: avaxKC, +// ethKC: ethKC, +// backend: backend, +// } +// } + +// func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { +// tx := &evm.Tx{UnsignedAtomicTx: utx} +// return tx, s.SignAtomic(ctx, tx) +// } + +// func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { +// switch utx := tx.UnsignedAtomicTx.(type) { +// case *evm.UnsignedImportTx: +// signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) +// if err != nil { +// return err +// } +// return sign(tx, true, signers) +// case *evm.UnsignedExportTx: +// signers := s.getExportSigners(utx.Ins) +// return sign(tx, true, signers) +// default: +// return fmt.Errorf("%w: %T", errUnknownTxType, tx) +// } +// } + +// func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { +// txSigners := make([][]keychain.Signer, len(ins)) +// for credIndex, transferInput := range ins { +// input, ok := transferInput.In.(*secp256k1fx.TransferInput) +// if !ok { +// return nil, errUnknownInputType +// } + +// inputSigners := make([]keychain.Signer, len(input.SigIndices)) +// txSigners[credIndex] = inputSigners + +// utxoID := transferInput.InputID() +// utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) +// if err == database.ErrNotFound { +// // If we don't have access to the UTXO, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// if err != nil { +// return nil, err +// } + +// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) +// if !ok { +// return nil, errUnknownOutputType +// } + +// for sigIndex, addrIndex := range input.SigIndices { +// if addrIndex >= uint32(len(out.Addrs)) { +// return nil, errInvalidUTXOSigIndex +// } + +// addr := out.Addrs[addrIndex] +// key, ok := s.avaxKC.Get(addr) +// if !ok { +// // If we don't have access to the key, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// inputSigners[sigIndex] = key +// } +// } +// return txSigners, nil +// } + +// func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { +// txSigners := make([][]keychain.Signer, len(ins)) +// for credIndex, input := range ins { +// inputSigners := make([]keychain.Signer, 1) +// txSigners[credIndex] = inputSigners + +// key, ok := s.ethKC.GetEth(input.Address) +// if !ok { +// // If we don't have access to the key, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// inputSigners[0] = key +// } +// return txSigners +// } + +// // TODO: remove [signHash] after the ledger supports signing all transactions. +// func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { +// unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) +// if err != nil { +// return fmt.Errorf("couldn't marshal unsigned tx: %w", err) +// } +// unsignedHash := hashing.ComputeHash256(unsignedBytes) + +// if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { +// tx.Creds = make([]verify.Verifiable, expectedLen) +// } + +// sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) +// for credIndex, inputSigners := range txSigners { +// credIntf := tx.Creds[credIndex] +// if credIntf == nil { +// credIntf = &secp256k1fx.Credential{} +// tx.Creds[credIndex] = credIntf +// } + +// cred, ok := credIntf.(*secp256k1fx.Credential) +// if !ok { +// return errUnknownCredentialType +// } +// if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { +// cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) +// } + +// for sigIndex, signer := range inputSigners { +// if signer == nil { +// // If we don't have access to the key, then we can't sign this +// // transaction. However, we can attempt to partially sign it. +// continue +// } +// addr := signer.Address() +// if sig := cred.Sigs[sigIndex]; sig != emptySig { +// // If this signature has already been populated, we can just +// // copy the needed signature for the future. +// sigCache[addr] = sig +// continue +// } + +// if sig, exists := sigCache[addr]; exists { +// // If this key has already produced a signature, we can just +// // copy the previous signature. +// cred.Sigs[sigIndex] = sig +// continue +// } + +// var sig []byte +// if signHash { +// sig, err = signer.SignHash(unsignedHash) +// } else { +// sig, err = signer.Sign(unsignedBytes) +// } +// if err != nil { +// return fmt.Errorf("problem signing tx: %w", err) +// } +// copy(cred.Sigs[sigIndex][:], sig) +// sigCache[addr] = cred.Sigs[sigIndex] +// } +// } + +// signedBytes, err := evm.Codec.Marshal(version, tx) +// if err != nil { +// return fmt.Errorf("couldn't marshal tx: %w", err) +// } +// tx.Initialize(unsignedBytes, signedBytes) +// return nil +// } diff --git a/wallet/chain/c/wallet.go b/wallet/chain/c/wallet.go index fb1a83d53dad..ebee50a9a958 100644 --- a/wallet/chain/c/wallet.go +++ b/wallet/chain/c/wallet.go @@ -3,204 +3,204 @@ package c -import ( - "errors" - "math/big" - "time" - - "github.com/ava-labs/coreth/ethclient" - "github.com/ava-labs/coreth/plugin/evm" - - ethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) - -var ( - _ Wallet = (*wallet)(nil) - - errNotCommitted = errors.New("not committed") -) - -type Wallet interface { - Context - - // Builder returns the builder that will be used to create the transactions. - Builder() Builder - - // Signer returns the signer that will be used to sign the transactions. - Signer() Signer - - // IssueImportTx creates, signs, and issues an import transaction that - // attempts to consume all the available UTXOs and import the funds to [to]. - // - // - [chainID] specifies the chain to be importing funds from. - // - [to] specifies where to send the imported funds to. - IssueImportTx( - chainID ids.ID, - to ethcommon.Address, - options ...common.Option, - ) (*evm.Tx, error) - - // IssueExportTx creates, signs, and issues an export transaction that - // attempts to send all the provided [outputs] to the requested [chainID]. - // - // - [chainID] specifies the chain to be exporting the funds to. - // - [outputs] specifies the outputs to send to the [chainID]. - IssueExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - options ...common.Option, - ) (*evm.Tx, error) - - // IssueUnsignedTx signs and issues the unsigned tx. - IssueUnsignedAtomicTx( - utx evm.UnsignedAtomicTx, - options ...common.Option, - ) (*evm.Tx, error) - - // IssueAtomicTx issues the signed tx. - IssueAtomicTx( - tx *evm.Tx, - options ...common.Option, - ) error -} - -func NewWallet( - builder Builder, - signer Signer, - avaxClient evm.Client, - ethClient ethclient.Client, - backend Backend, -) Wallet { - return &wallet{ - Backend: backend, - builder: builder, - signer: signer, - avaxClient: avaxClient, - ethClient: ethClient, - } -} - -type wallet struct { - Backend - builder Builder - signer Signer - avaxClient evm.Client - ethClient ethclient.Client -} - -func (w *wallet) Builder() Builder { - return w.builder -} - -func (w *wallet) Signer() Signer { - return w.signer -} - -func (w *wallet) IssueImportTx( - chainID ids.ID, - to ethcommon.Address, - options ...common.Option, -) (*evm.Tx, error) { - baseFee, err := w.baseFee(options) - if err != nil { - return nil, err - } - - utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) - if err != nil { - return nil, err - } - return w.IssueUnsignedAtomicTx(utx, options...) -} - -func (w *wallet) IssueExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - options ...common.Option, -) (*evm.Tx, error) { - baseFee, err := w.baseFee(options) - if err != nil { - return nil, err - } - - utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) - if err != nil { - return nil, err - } - return w.IssueUnsignedAtomicTx(utx, options...) -} - -func (w *wallet) IssueUnsignedAtomicTx( - utx evm.UnsignedAtomicTx, - options ...common.Option, -) (*evm.Tx, error) { - ops := common.NewOptions(options) - ctx := ops.Context() - tx, err := w.signer.SignUnsignedAtomic(ctx, utx) - if err != nil { - return nil, err - } - - return tx, w.IssueAtomicTx(tx, options...) -} - -func (w *wallet) IssueAtomicTx( - tx *evm.Tx, - options ...common.Option, -) error { - ops := common.NewOptions(options) - ctx := ops.Context() - txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) - if err != nil { - return err - } - - if f := ops.PostIssuanceFunc(); f != nil { - f(txID) - } - - if ops.AssumeDecided() { - return w.Backend.AcceptAtomicTx(ctx, tx) - } - - pollFrequency := ops.PollFrequency() - ticker := time.NewTicker(pollFrequency) - defer ticker.Stop() - - for { - status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) - if err != nil { - return err - } - - switch status { - case evm.Accepted: - return w.Backend.AcceptAtomicTx(ctx, tx) - case evm.Dropped, evm.Unknown: - return errNotCommitted - } - - // The tx is Processing. - - select { - case <-ticker.C: - case <-ctx.Done(): - return ctx.Err() - } - } -} - -func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { - ops := common.NewOptions(options) - baseFee := ops.BaseFee(nil) - if baseFee != nil { - return baseFee, nil - } - - ctx := ops.Context() - return w.ethClient.EstimateBaseFee(ctx) -} +// import ( +// "errors" +// "math/big" +// "time" + +// "github.com/ava-labs/coreth/ethclient" +// "github.com/ava-labs/coreth/plugin/evm" + +// ethcommon "github.com/ethereum/go-ethereum/common" + +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) + +// var ( +// _ Wallet = (*wallet)(nil) + +// errNotCommitted = errors.New("not committed") +// ) + +// type Wallet interface { +// Context + +// // Builder returns the builder that will be used to create the transactions. +// Builder() Builder + +// // Signer returns the signer that will be used to sign the transactions. +// Signer() Signer + +// // IssueImportTx creates, signs, and issues an import transaction that +// // attempts to consume all the available UTXOs and import the funds to [to]. +// // +// // - [chainID] specifies the chain to be importing funds from. +// // - [to] specifies where to send the imported funds to. +// IssueImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// options ...common.Option, +// ) (*evm.Tx, error) + +// // IssueExportTx creates, signs, and issues an export transaction that +// // attempts to send all the provided [outputs] to the requested [chainID]. +// // +// // - [chainID] specifies the chain to be exporting the funds to. +// // - [outputs] specifies the outputs to send to the [chainID]. +// IssueExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// options ...common.Option, +// ) (*evm.Tx, error) + +// // IssueUnsignedTx signs and issues the unsigned tx. +// IssueUnsignedAtomicTx( +// utx evm.UnsignedAtomicTx, +// options ...common.Option, +// ) (*evm.Tx, error) + +// // IssueAtomicTx issues the signed tx. +// IssueAtomicTx( +// tx *evm.Tx, +// options ...common.Option, +// ) error +// } + +// func NewWallet( +// builder Builder, +// signer Signer, +// avaxClient evm.Client, +// ethClient ethclient.Client, +// backend Backend, +// ) Wallet { +// return &wallet{ +// Backend: backend, +// builder: builder, +// signer: signer, +// avaxClient: avaxClient, +// ethClient: ethClient, +// } +// } + +// type wallet struct { +// Backend +// builder Builder +// signer Signer +// avaxClient evm.Client +// ethClient ethclient.Client +// } + +// func (w *wallet) Builder() Builder { +// return w.builder +// } + +// func (w *wallet) Signer() Signer { +// return w.signer +// } + +// func (w *wallet) IssueImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// options ...common.Option, +// ) (*evm.Tx, error) { +// baseFee, err := w.baseFee(options) +// if err != nil { +// return nil, err +// } + +// utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) +// if err != nil { +// return nil, err +// } +// return w.IssueUnsignedAtomicTx(utx, options...) +// } + +// func (w *wallet) IssueExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// options ...common.Option, +// ) (*evm.Tx, error) { +// baseFee, err := w.baseFee(options) +// if err != nil { +// return nil, err +// } + +// utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) +// if err != nil { +// return nil, err +// } +// return w.IssueUnsignedAtomicTx(utx, options...) +// } + +// func (w *wallet) IssueUnsignedAtomicTx( +// utx evm.UnsignedAtomicTx, +// options ...common.Option, +// ) (*evm.Tx, error) { +// ops := common.NewOptions(options) +// ctx := ops.Context() +// tx, err := w.signer.SignUnsignedAtomic(ctx, utx) +// if err != nil { +// return nil, err +// } + +// return tx, w.IssueAtomicTx(tx, options...) +// } + +// func (w *wallet) IssueAtomicTx( +// tx *evm.Tx, +// options ...common.Option, +// ) error { +// ops := common.NewOptions(options) +// ctx := ops.Context() +// txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) +// if err != nil { +// return err +// } + +// if f := ops.PostIssuanceFunc(); f != nil { +// f(txID) +// } + +// if ops.AssumeDecided() { +// return w.Backend.AcceptAtomicTx(ctx, tx) +// } + +// pollFrequency := ops.PollFrequency() +// ticker := time.NewTicker(pollFrequency) +// defer ticker.Stop() + +// for { +// status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) +// if err != nil { +// return err +// } + +// switch status { +// case evm.Accepted: +// return w.Backend.AcceptAtomicTx(ctx, tx) +// case evm.Dropped, evm.Unknown: +// return errNotCommitted +// } + +// // The tx is Processing. + +// select { +// case <-ticker.C: +// case <-ctx.Done(): +// return ctx.Err() +// } +// } +// } + +// func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { +// ops := common.NewOptions(options) +// baseFee := ops.BaseFee(nil) +// if baseFee != nil { +// return baseFee, nil +// } + +// ctx := ops.Context() +// return w.ethClient.EstimateBaseFee(ctx) +// } diff --git a/wallet/chain/c/wallet_with_options.go b/wallet/chain/c/wallet_with_options.go index 7d6193683d49..fd69a6d4fd02 100644 --- a/wallet/chain/c/wallet_with_options.go +++ b/wallet/chain/c/wallet_with_options.go @@ -3,80 +3,80 @@ package c -import ( - "github.com/ava-labs/coreth/plugin/evm" +// import ( +// "github.com/ava-labs/coreth/plugin/evm" - ethcommon "github.com/ethereum/go-ethereum/common" +// ethcommon "github.com/ethereum/go-ethereum/common" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -) +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +// ) -var _ Wallet = (*walletWithOptions)(nil) +// var _ Wallet = (*walletWithOptions)(nil) -func NewWalletWithOptions( - wallet Wallet, - options ...common.Option, -) Wallet { - return &walletWithOptions{ - Wallet: wallet, - options: options, - } -} +// func NewWalletWithOptions( +// wallet Wallet, +// options ...common.Option, +// ) Wallet { +// return &walletWithOptions{ +// Wallet: wallet, +// options: options, +// } +// } -type walletWithOptions struct { - Wallet - options []common.Option -} +// type walletWithOptions struct { +// Wallet +// options []common.Option +// } -func (w *walletWithOptions) Builder() Builder { - return NewBuilderWithOptions( - w.Wallet.Builder(), - w.options..., - ) -} +// func (w *walletWithOptions) Builder() Builder { +// return NewBuilderWithOptions( +// w.Wallet.Builder(), +// w.options..., +// ) +// } -func (w *walletWithOptions) IssueImportTx( - chainID ids.ID, - to ethcommon.Address, - options ...common.Option, -) (*evm.Tx, error) { - return w.Wallet.IssueImportTx( - chainID, - to, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueImportTx( +// chainID ids.ID, +// to ethcommon.Address, +// options ...common.Option, +// ) (*evm.Tx, error) { +// return w.Wallet.IssueImportTx( +// chainID, +// to, +// common.UnionOptions(w.options, options)..., +// ) +// } -func (w *walletWithOptions) IssueExportTx( - chainID ids.ID, - outputs []*secp256k1fx.TransferOutput, - options ...common.Option, -) (*evm.Tx, error) { - return w.Wallet.IssueExportTx( - chainID, - outputs, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueExportTx( +// chainID ids.ID, +// outputs []*secp256k1fx.TransferOutput, +// options ...common.Option, +// ) (*evm.Tx, error) { +// return w.Wallet.IssueExportTx( +// chainID, +// outputs, +// common.UnionOptions(w.options, options)..., +// ) +// } -func (w *walletWithOptions) IssueUnsignedAtomicTx( - utx evm.UnsignedAtomicTx, - options ...common.Option, -) (*evm.Tx, error) { - return w.Wallet.IssueUnsignedAtomicTx( - utx, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueUnsignedAtomicTx( +// utx evm.UnsignedAtomicTx, +// options ...common.Option, +// ) (*evm.Tx, error) { +// return w.Wallet.IssueUnsignedAtomicTx( +// utx, +// common.UnionOptions(w.options, options)..., +// ) +// } -func (w *walletWithOptions) IssueAtomicTx( - tx *evm.Tx, - options ...common.Option, -) error { - return w.Wallet.IssueAtomicTx( - tx, - common.UnionOptions(w.options, options)..., - ) -} +// func (w *walletWithOptions) IssueAtomicTx( +// tx *evm.Tx, +// options ...common.Option, +// ) error { +// return w.Wallet.IssueAtomicTx( +// tx, +// common.UnionOptions(w.options, options)..., +// ) +// } diff --git a/wallet/subnet/primary/api.go b/wallet/subnet/primary/api.go index 3ac72c217884..3260c05a0a1b 100644 --- a/wallet/subnet/primary/api.go +++ b/wallet/subnet/primary/api.go @@ -5,12 +5,6 @@ package primary import ( "context" - "fmt" - - "github.com/ava-labs/coreth/ethclient" - "github.com/ava-labs/coreth/plugin/evm" - - "github.com/ethereum/go-ethereum/common" "github.com/ava-labs/avalanchego/api/info" "github.com/ava-labs/avalanchego/codec" @@ -22,7 +16,6 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm" "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" ) @@ -59,9 +52,9 @@ type AVAXState struct { PCTX p.Context XClient avm.Client XCTX x.Context - CClient evm.Client - CCTX c.Context - UTXOs UTXOs + // CClient evm.Client + // CCTX c.Context + UTXOs UTXOs } func FetchState( @@ -75,7 +68,7 @@ func FetchState( infoClient := info.NewClient(uri) pClient := platformvm.NewClient(uri) xClient := avm.NewClient(uri, "X") - cClient := evm.NewCChainClient(uri) + // cClient := evm.NewCChainClient(uri) pCTX, err := p.NewContextFromClients(ctx, infoClient, xClient) if err != nil { @@ -87,10 +80,10 @@ func FetchState( return nil, err } - cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) - if err != nil { - return nil, err - } + // cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) + // if err != nil { + // return nil, err + // } utxos := NewUTXOs() addrList := addrs.List() @@ -109,11 +102,11 @@ func FetchState( client: xClient, codec: x.Parser.Codec(), }, - { - id: cCTX.BlockchainID(), - client: cClient, - codec: evm.Codec, - }, + // { + // id: cCTX.BlockchainID(), + // client: cClient, + // codec: evm.Codec, + // }, } for _, destinationChain := range chains { for _, sourceChain := range chains { @@ -136,52 +129,52 @@ func FetchState( PCTX: pCTX, XClient: xClient, XCTX: xCTX, - CClient: cClient, - CCTX: cCTX, - UTXOs: utxos, + // CClient: cClient, + // CCTX: cCTX, + UTXOs: utxos, }, nil } -type EthState struct { - Client ethclient.Client - Accounts map[common.Address]*c.Account -} - -func FetchEthState( - ctx context.Context, - uri string, - addrs set.Set[common.Address], -) (*EthState, error) { - path := fmt.Sprintf( - "%s/ext/%s/C/rpc", - uri, - constants.ChainAliasPrefix, - ) - client, err := ethclient.Dial(path) - if err != nil { - return nil, err - } - - accounts := make(map[common.Address]*c.Account, addrs.Len()) - for addr := range addrs { - balance, err := client.BalanceAt(ctx, addr, nil) - if err != nil { - return nil, err - } - nonce, err := client.NonceAt(ctx, addr, nil) - if err != nil { - return nil, err - } - accounts[addr] = &c.Account{ - Balance: balance, - Nonce: nonce, - } - } - return &EthState{ - Client: client, - Accounts: accounts, - }, nil -} +// type EthState struct { +// Client ethclient.Client +// Accounts map[common.Address]*c.Account +// } + +// func FetchEthState( +// ctx context.Context, +// uri string, +// addrs set.Set[common.Address], +// ) (*EthState, error) { +// path := fmt.Sprintf( +// "%s/ext/%s/C/rpc", +// uri, +// constants.ChainAliasPrefix, +// ) +// client, err := ethclient.Dial(path) +// if err != nil { +// return nil, err +// } + +// accounts := make(map[common.Address]*c.Account, addrs.Len()) +// for addr := range addrs { +// balance, err := client.BalanceAt(ctx, addr, nil) +// if err != nil { +// return nil, err +// } +// nonce, err := client.NonceAt(ctx, addr, nil) +// if err != nil { +// return nil, err +// } +// accounts[addr] = &c.Account{ +// Balance: balance, +// Nonce: nonce, +// } +// } +// return &EthState{ +// Client: client, +// Accounts: accounts, +// }, nil +// } // AddAllUTXOs fetches all the UTXOs referenced by [addresses] that were sent // from [sourceChainID] to [destinationChainID] from the [client]. It then uses diff --git a/wallet/subnet/primary/example_test.go b/wallet/subnet/primary/example_test.go index 483c049d4ac0..4a73e8c070b2 100644 --- a/wallet/subnet/primary/example_test.go +++ b/wallet/subnet/primary/example_test.go @@ -30,7 +30,7 @@ func ExampleWallet() { wallet, err := MakeWallet(ctx, &WalletConfig{ URI: LocalAPIURI, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet with: %s\n", err) diff --git a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go index d5e8ce422307..21c081d2982b 100644 --- a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go @@ -46,9 +46,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/add-primary-validator/main.go b/wallet/subnet/primary/examples/add-primary-validator/main.go index a56dae23db3a..13c28f995f63 100644 --- a/wallet/subnet/primary/examples/add-primary-validator/main.go +++ b/wallet/subnet/primary/examples/add-primary-validator/main.go @@ -45,7 +45,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/c-chain-export/main.go b/wallet/subnet/primary/examples/c-chain-export/main.go index fec55c899feb..a6b9a0c810b8 100644 --- a/wallet/subnet/primary/examples/c-chain-export/main.go +++ b/wallet/subnet/primary/examples/c-chain-export/main.go @@ -3,70 +3,70 @@ package main -import ( - "context" - "log" - "time" +// import ( +// "context" +// "log" +// "time" - "github.com/ava-labs/avalanchego/genesis" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary" -) +// "github.com/ava-labs/avalanchego/genesis" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary" +// ) -func main() { - key := genesis.EWOQKey - uri := primary.LocalAPIURI - kc := secp256k1fx.NewKeychain(key) - avaxAddr := key.Address() +// func main() { +// key := genesis.EWOQKey +// uri := primary.LocalAPIURI +// kc := secp256k1fx.NewKeychain(key) +// avaxAddr := key.Address() - ctx := context.Background() +// ctx := context.Background() - // MakeWallet fetches the available UTXOs owned by [kc] on the network that - // [uri] is hosting. - walletSyncStartTime := time.Now() - wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, - }) - if err != nil { - log.Fatalf("failed to initialize wallet: %s\n", err) - } - log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) +// // MakeWallet fetches the available UTXOs owned by [kc] on the network that +// // [uri] is hosting. +// walletSyncStartTime := time.Now() +// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ +// URI: uri, +// AVAXKeychain: kc, +// EthKeychain: kc, +// }) +// if err != nil { +// log.Fatalf("failed to initialize wallet: %s\n", err) +// } +// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) - // Get the P-chain wallet - pWallet := wallet.P() - cWallet := wallet.C() +// // Get the P-chain wallet +// pWallet := wallet.P() +// cWallet := wallet.C() - // Pull out useful constants to use when issuing transactions. - cChainID := cWallet.BlockchainID() - owner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - avaxAddr, - }, - } +// // Pull out useful constants to use when issuing transactions. +// cChainID := cWallet.BlockchainID() +// owner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// avaxAddr, +// }, +// } - exportStartTime := time.Now() - exportTx, err := cWallet.IssueExportTx( - constants.PlatformChainID, - []*secp256k1fx.TransferOutput{{ - Amt: units.Avax, - OutputOwners: owner, - }}, - ) - if err != nil { - log.Fatalf("failed to issue export transaction: %s\n", err) - } - log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) +// exportStartTime := time.Now() +// exportTx, err := cWallet.IssueExportTx( +// constants.PlatformChainID, +// []*secp256k1fx.TransferOutput{{ +// Amt: units.Avax, +// OutputOwners: owner, +// }}, +// ) +// if err != nil { +// log.Fatalf("failed to issue export transaction: %s\n", err) +// } +// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) - importStartTime := time.Now() - importTx, err := pWallet.IssueImportTx(cChainID, &owner) - if err != nil { - log.Fatalf("failed to issue import transaction: %s\n", err) - } - log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) -} +// importStartTime := time.Now() +// importTx, err := pWallet.IssueImportTx(cChainID, &owner) +// if err != nil { +// log.Fatalf("failed to issue import transaction: %s\n", err) +// } +// log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) +// } diff --git a/wallet/subnet/primary/examples/c-chain-import/main.go b/wallet/subnet/primary/examples/c-chain-import/main.go index b4dc4e603eb3..2d9b8a244cb0 100644 --- a/wallet/subnet/primary/examples/c-chain-import/main.go +++ b/wallet/subnet/primary/examples/c-chain-import/main.go @@ -3,75 +3,75 @@ package main -import ( - "context" - "log" - "time" +// import ( +// "context" +// "log" +// "time" - "github.com/ava-labs/coreth/plugin/evm" +// "github.com/ava-labs/coreth/plugin/evm" - "github.com/ava-labs/avalanchego/genesis" - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/constants" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/vms/components/avax" - "github.com/ava-labs/avalanchego/vms/secp256k1fx" - "github.com/ava-labs/avalanchego/wallet/subnet/primary" -) +// "github.com/ava-labs/avalanchego/genesis" +// "github.com/ava-labs/avalanchego/ids" +// "github.com/ava-labs/avalanchego/utils/constants" +// "github.com/ava-labs/avalanchego/utils/units" +// "github.com/ava-labs/avalanchego/vms/components/avax" +// "github.com/ava-labs/avalanchego/vms/secp256k1fx" +// "github.com/ava-labs/avalanchego/wallet/subnet/primary" +// ) -func main() { - key := genesis.EWOQKey - uri := primary.LocalAPIURI - kc := secp256k1fx.NewKeychain(key) - avaxAddr := key.Address() - ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) +// func main() { +// key := genesis.EWOQKey +// uri := primary.LocalAPIURI +// kc := secp256k1fx.NewKeychain(key) +// avaxAddr := key.Address() +// ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) - ctx := context.Background() +// ctx := context.Background() - // MakeWallet fetches the available UTXOs owned by [kc] on the network that - // [uri] is hosting. - walletSyncStartTime := time.Now() - wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, - }) - if err != nil { - log.Fatalf("failed to initialize wallet: %s\n", err) - } - log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) +// // MakeWallet fetches the available UTXOs owned by [kc] on the network that +// // [uri] is hosting. +// walletSyncStartTime := time.Now() +// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ +// URI: uri, +// AVAXKeychain: kc, +// EthKeychain: kc, +// }) +// if err != nil { +// log.Fatalf("failed to initialize wallet: %s\n", err) +// } +// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) - // Get the P-chain wallet - pWallet := wallet.P() - cWallet := wallet.C() +// // Get the P-chain wallet +// pWallet := wallet.P() +// cWallet := wallet.C() - // Pull out useful constants to use when issuing transactions. - cChainID := cWallet.BlockchainID() - avaxAssetID := cWallet.AVAXAssetID() - owner := secp256k1fx.OutputOwners{ - Threshold: 1, - Addrs: []ids.ShortID{ - avaxAddr, - }, - } +// // Pull out useful constants to use when issuing transactions. +// cChainID := cWallet.BlockchainID() +// avaxAssetID := cWallet.AVAXAssetID() +// owner := secp256k1fx.OutputOwners{ +// Threshold: 1, +// Addrs: []ids.ShortID{ +// avaxAddr, +// }, +// } - exportStartTime := time.Now() - exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ - Asset: avax.Asset{ID: avaxAssetID}, - Out: &secp256k1fx.TransferOutput{ - Amt: units.Avax, - OutputOwners: owner, - }, - }}) - if err != nil { - log.Fatalf("failed to issue export transaction: %s\n", err) - } - log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) +// exportStartTime := time.Now() +// exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ +// Asset: avax.Asset{ID: avaxAssetID}, +// Out: &secp256k1fx.TransferOutput{ +// Amt: units.Avax, +// OutputOwners: owner, +// }, +// }}) +// if err != nil { +// log.Fatalf("failed to issue export transaction: %s\n", err) +// } +// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) - importStartTime := time.Now() - importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) - if err != nil { - log.Fatalf("failed to issue import transaction: %s\n", err) - } - log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) -} +// importStartTime := time.Now() +// importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) +// if err != nil { +// log.Fatalf("failed to issue import transaction: %s\n", err) +// } +// log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) +// } diff --git a/wallet/subnet/primary/examples/create-asset/main.go b/wallet/subnet/primary/examples/create-asset/main.go index 30804f083df6..0bccfbb5fc52 100644 --- a/wallet/subnet/primary/examples/create-asset/main.go +++ b/wallet/subnet/primary/examples/create-asset/main.go @@ -30,7 +30,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-chain/main.go b/wallet/subnet/primary/examples/create-chain/main.go index 5e6898a1b649..521a3cca53cf 100644 --- a/wallet/subnet/primary/examples/create-chain/main.go +++ b/wallet/subnet/primary/examples/create-chain/main.go @@ -41,9 +41,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/create-locked-stakeable/main.go b/wallet/subnet/primary/examples/create-locked-stakeable/main.go index e688968e9e8a..92f1b5cb0e1b 100644 --- a/wallet/subnet/primary/examples/create-locked-stakeable/main.go +++ b/wallet/subnet/primary/examples/create-locked-stakeable/main.go @@ -39,7 +39,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-subnet/main.go b/wallet/subnet/primary/examples/create-subnet/main.go index add98ea7931c..3e8d69bc016a 100644 --- a/wallet/subnet/primary/examples/create-subnet/main.go +++ b/wallet/subnet/primary/examples/create-subnet/main.go @@ -28,7 +28,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - EthKeychain: kc, + // EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/remove-subnet-validator/main.go b/wallet/subnet/primary/examples/remove-subnet-validator/main.go index 2842c7c0a790..46f4b85124db 100644 --- a/wallet/subnet/primary/examples/remove-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/remove-subnet-validator/main.go @@ -38,9 +38,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + // EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/wallet.go b/wallet/subnet/primary/wallet.go index 54de390d029c..de50d12f866b 100644 --- a/wallet/subnet/primary/wallet.go +++ b/wallet/subnet/primary/wallet.go @@ -11,7 +11,6 @@ import ( "github.com/ava-labs/avalanchego/utils/crypto/keychain" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/platformvm/txs" - "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" @@ -23,13 +22,13 @@ var _ Wallet = (*wallet)(nil) type Wallet interface { P() p.Wallet X() x.Wallet - C() c.Wallet + // C() c.Wallet } type wallet struct { p p.Wallet x x.Wallet - c c.Wallet + // c c.Wallet } func (w *wallet) P() p.Wallet { @@ -40,16 +39,16 @@ func (w *wallet) X() x.Wallet { return w.x } -func (w *wallet) C() c.Wallet { - return w.c -} +// func (w *wallet) C() c.Wallet { +// return w.c +// } // Creates a new default wallet -func NewWallet(p p.Wallet, x x.Wallet, c c.Wallet) Wallet { +func NewWallet(p p.Wallet, x x.Wallet /*, c c.Wallet*/) Wallet { return &wallet{ p: p, x: x, - c: c, + // c: c, } } @@ -58,7 +57,7 @@ func NewWalletWithOptions(w Wallet, options ...common.Option) Wallet { return NewWallet( p.NewWalletWithOptions(w.P(), options...), x.NewWalletWithOptions(w.X(), options...), - c.NewWalletWithOptions(w.C(), options...), + // c.NewWalletWithOptions(w.C(), options...), ) } @@ -67,7 +66,7 @@ type WalletConfig struct { URI string // required // Keys to use for signing all transactions. AVAXKeychain keychain.Keychain // required - EthKeychain c.EthKeychain // required + // EthKeychain c.EthKeychain // required // Set of P-chain transactions that the wallet should know about to be able // to generate transactions. PChainTxs map[ids.ID]*txs.Tx // optional @@ -93,11 +92,11 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { return nil, err } - ethAddrs := config.EthKeychain.EthAddresses() - ethState, err := FetchEthState(ctx, config.URI, ethAddrs) - if err != nil { - return nil, err - } + // ethAddrs := config.EthKeychain.EthAddresses() + // ethState, err := FetchEthState(ctx, config.URI, ethAddrs) + // if err != nil { + // return nil, err + // } pChainTxs := config.PChainTxs if pChainTxs == nil { @@ -127,15 +126,15 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { xBuilder := x.NewBuilder(avaxAddrs, xBackend) xSigner := x.NewSigner(config.AVAXKeychain, xBackend) - cChainID := avaxState.CCTX.BlockchainID() - cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) - cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) - cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) - cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) + // cChainID := avaxState.CCTX.BlockchainID() + // cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) + // cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) + // cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) + // cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) return NewWallet( p.NewWallet(pBuilder, pSigner, avaxState.PClient, pBackend), x.NewWallet(xBuilder, xSigner, avaxState.XClient, xBackend), - c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), + // c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), ), nil } From 40215d1306a72290592be3e63a35daff006d4b14 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Sun, 19 Nov 2023 22:39:25 +0100 Subject: [PATCH 34/36] bumped coreth version --- go.mod | 25 + go.sum | 76 ++ node/node.go | 4 +- tests/e2e/c/dynamic_fees.go | 326 +++---- tests/e2e/c/interchain_workflow.go | 320 +++---- tests/e2e/p/interchain_workflow.go | 444 +++++----- tests/e2e/x/interchain_workflow.go | 296 +++---- tests/fixture/e2e/helpers.go | 110 +-- tests/fixture/testnet/config.go | 54 +- vms/example/xsvm/cmd/chain/create/cmd.go | 6 +- wallet/chain/c/backend.go | 300 +++---- wallet/chain/c/builder.go | 792 +++++++++--------- wallet/chain/c/builder_with_options.go | 136 +-- wallet/chain/c/context.go | 130 +-- wallet/chain/c/signer.go | 436 +++++----- wallet/chain/c/wallet.go | 402 ++++----- wallet/chain/c/wallet_with_options.go | 134 +-- wallet/subnet/primary/api.go | 119 +-- wallet/subnet/primary/example_test.go | 2 +- .../add-permissioned-subnet-validator/main.go | 6 +- .../examples/add-primary-validator/main.go | 2 +- .../primary/examples/c-chain-export/main.go | 118 +-- .../primary/examples/c-chain-import/main.go | 126 +-- .../primary/examples/create-asset/main.go | 2 +- .../primary/examples/create-chain/main.go | 6 +- .../examples/create-locked-stakeable/main.go | 2 +- .../primary/examples/create-subnet/main.go | 2 +- .../examples/remove-subnet-validator/main.go | 6 +- wallet/subnet/primary/wallet.go | 41 +- 29 files changed, 2270 insertions(+), 2153 deletions(-) diff --git a/go.mod b/go.mod index 23b752198fdd..48a1872af8b7 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/DataDog/zstd v1.5.2 github.com/Microsoft/go-winio v0.5.2 github.com/NYTimes/gziphandler v1.1.1 + github.com/ava-labs/coreth v0.12.9-rc.0.0.20231119212828-5c2f81b3e67e github.com/ava-labs/ledger-avalanche/go v0.0.0-20231102202641-ae2ebdaeac34 github.com/btcsuite/btcd/btcutil v1.1.3 github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 @@ -74,6 +75,7 @@ require ( github.com/BurntSushi/toml v1.2.1 // indirect github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/VictoriaMetrics/fastcache v1.10.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect @@ -81,26 +83,44 @@ require ( github.com/cockroachdb/errors v1.9.1 // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/redact v1.1.3 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/deckarep/golang-set/v2 v2.1.0 // indirect + github.com/dlclark/regexp2 v1.7.0 // indirect + github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 // indirect + github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect github.com/frankban/quicktest v1.14.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect + github.com/go-stack/stack v1.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/go-cmp v0.5.9 // indirect + github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 // indirect + github.com/hashicorp/go-bexpr v0.1.10 // indirect + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e // indirect github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/klauspost/compress v1.15.15 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/magiconair/properties v1.8.6 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mitchellh/pointerstructure v1.2.0 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect @@ -108,12 +128,17 @@ require ( github.com/prometheus/common v0.39.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sanity-io/litter v1.5.1 // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/status-im/keycard-go v0.2.0 // indirect github.com/subosito/gotenv v1.3.0 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa // indirect + github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/zondax/hid v0.9.2 // indirect github.com/zondax/ledger-go v0.14.3 // indirect diff --git a/go.sum b/go.sum index 2ae152b17faf..e6e70254d8ff 100644 --- a/go.sum +++ b/go.sum @@ -56,12 +56,18 @@ github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cq github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= +github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY= +github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/ava-labs/coreth v0.12.9-rc.0.0.20231119212828-5c2f81b3e67e h1:bneqYlrcOqHO9ZhK4+tjbZfv5+ACQU1C7MEUCmIIEv0= +github.com/ava-labs/coreth v0.12.9-rc.0.0.20231119212828-5c2f81b3e67e/go.mod h1:/y47f0Vg2LrnsQI9aUGOrEOb4oNOilAV29X4ITyJK7c= github.com/ava-labs/ledger-avalanche/go v0.0.0-20231102202641-ae2ebdaeac34 h1:mg9Uw6oZFJKytJxgxnl3uxZOs/SB8CVHg6Io4Tf99Zc= github.com/ava-labs/ledger-avalanche/go v0.0.0-20231102202641-ae2ebdaeac34/go.mod h1:pJxaT9bUgeRNVmNRgtCHb7sFDIRKy7CzTQVi8gGNT6g= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= @@ -96,13 +102,18 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= @@ -134,12 +145,16 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= +github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= @@ -150,6 +165,14 @@ github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6ps github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= +github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3 h1:+3HCtB74++ClLy8GgjUQYeC8R4ILzVcIe8+5edAJJnE= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= +github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= +github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -166,6 +189,8 @@ github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2 github.com/ethereum/go-ethereum v1.12.0/go.mod h1:/oo2X/dZLJjf2mJ6YT9wcWxa4nNJDBKDBU6sFIpx1Gs= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -174,6 +199,8 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= @@ -197,7 +224,11 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= @@ -282,10 +313,14 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -306,11 +341,17 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 h1:kr3j8iIMR4ywO/O0rvksXaJvauGGCMg2zAZIiNZ9uIQ= github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0/go.mod h1:ummNFgdgLhhX7aIiy35vVmQNS0rWXknfPE0qe6fmFXg= +github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw= +github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e/go.mod h1:j9cQbcqHQujT0oKJ38PylVfqohClLr3CvDC+Qcg+lhU= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8= @@ -322,6 +363,7 @@ github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3 github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -363,6 +405,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -370,6 +413,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= @@ -380,11 +424,17 @@ github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -393,8 +443,11 @@ github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -413,6 +466,8 @@ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -480,6 +535,8 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sanity-io/litter v1.5.1 h1:dwnrSypP6q56o3lFxTU+t2fwQ9A+U5qrXVO4Qg9KwVU= github.com/sanity-io/litter v1.5.1/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0= @@ -515,6 +572,8 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= +github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -546,10 +605,14 @@ github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZF github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q= +github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= @@ -561,6 +624,8 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1: github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= @@ -570,6 +635,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= @@ -665,6 +731,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -710,6 +777,7 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -733,6 +801,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -797,8 +866,12 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -815,6 +888,7 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -878,6 +952,7 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1002,6 +1077,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= diff --git a/node/node.go b/node/node.go index 98d697a66359..06544e8f9e6b 100644 --- a/node/node.go +++ b/node/node.go @@ -25,7 +25,7 @@ import ( "go.uber.org/zap" - // coreth "github.com/ava-labs/coreth/plugin/evm" + coreth "github.com/ava-labs/coreth/plugin/evm" "github.com/ava-labs/avalanchego/api/admin" "github.com/ava-labs/avalanchego/api/auth" @@ -1094,7 +1094,7 @@ func (n *Node) initVMs() error { CreateAssetTxFee: n.Config.CreateAssetTxFee, }, }), - // vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), + vmRegisterer.Register(context.TODO(), constants.EVMID, &coreth.Factory{}), n.VMManager.RegisterFactory(context.TODO(), secp256k1fx.ID, &secp256k1fx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), nftfx.ID, &nftfx.Factory{}), n.VMManager.RegisterFactory(context.TODO(), propertyfx.ID, &propertyfx.Factory{}), diff --git a/tests/e2e/c/dynamic_fees.go b/tests/e2e/c/dynamic_fees.go index 8748dda7451d..8f15b6d43caf 100644 --- a/tests/e2e/c/dynamic_fees.go +++ b/tests/e2e/c/dynamic_fees.go @@ -3,166 +3,166 @@ package c -// import ( -// "math/big" -// "strings" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/stretchr/testify/require" - -// "github.com/ethereum/go-ethereum/accounts/abi" -// "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/coreth/core/types" -// "github.com/ava-labs/coreth/params" -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/tests" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/tests/fixture/testnet" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// ) - -// // This test uses the compiled bin for `hashing.sol` as -// // well as its ABI contained in `hashing_contract.go`. - -// var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { -// require := require.New(ginkgo.GinkgoT()) - -// // Need a gas limit much larger than the standard 21_000 to enable -// // the contract to induce a gas price increase -// const largeGasLimit = uint64(8_000_000) - -// // TODO(marun) What is the significance of this value? -// gasTip := big.NewInt(1000 * params.GWei) - -// ginkgo.It("should ensure that the gas price is affected by load", func() { -// ginkgo.By("creating a new private network to ensure isolation from other tests") -// privateNetwork := e2e.Env.NewPrivateNetwork() - -// ginkgo.By("allocating a pre-funded key") -// key := privateNetwork.GetConfig().FundedKeys[0] -// ethAddress := evm.GetEthAddress(key) - -// ginkgo.By("initializing a coreth client") -// node := privateNetwork.GetNodes()[0] -// nodeURI := testnet.NodeURI{ -// NodeID: node.GetID(), -// URI: node.GetProcessContext().URI, -// } -// ethClient := e2e.NewEthClient(nodeURI) - -// ginkgo.By("initializing a transaction signer") -// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) -// require.NoError(err) -// signer := types.NewEIP155Signer(cChainID) -// ecdsaKey := key.ToECDSA() -// sign := func(tx *types.Transaction) *types.Transaction { -// signedTx, err := types.SignTx(tx, signer, ecdsaKey) -// require.NoError(err) -// return signedTx -// } - -// var contractAddress common.Address -// ginkgo.By("deploying an expensive contract", func() { -// // Create transaction -// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) -// require.NoError(err) -// compiledContract := common.Hex2Bytes(hashingCompiledContract) -// tx := types.NewTx(&types.LegacyTx{ -// Nonce: nonce, -// GasPrice: gasTip, -// Gas: largeGasLimit, -// Value: common.Big0, -// Data: compiledContract, -// }) - -// // Send the transaction and wait for acceptance -// signedTx := sign(tx) -// receipt := e2e.SendEthTransaction(ethClient, signedTx) - -// contractAddress = receipt.ContractAddress -// }) - -// var gasPrice *big.Int -// ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { -// // Evaluate the bytes representation of the contract -// hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) -// require.NoError(err) -// contractData, err := hashingABI.Pack("hashIt") -// require.NoError(err) - -// var initialGasPrice *big.Int -// e2e.Eventually(func() bool { -// // Check the gas price -// var err error -// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) -// require.NoError(err) -// if initialGasPrice == nil { -// initialGasPrice = gasPrice -// tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) -// } else if gasPrice.Cmp(initialGasPrice) > 0 { -// // Gas price has increased -// tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) -// return true -// } - -// // Create the transaction -// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) -// require.NoError(err) -// tx := types.NewTx(&types.LegacyTx{ -// Nonce: nonce, -// GasPrice: gasTip, -// Gas: largeGasLimit, -// To: &contractAddress, -// Value: common.Big0, -// Data: contractData, -// }) - -// // Send the transaction and wait for acceptance -// signedTx := sign(tx) -// _ = e2e.SendEthTransaction(ethClient, signedTx) - -// // The gas price will be checked at the start of the next iteration -// return false -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") -// }) - -// ginkgo.By("waiting for the gas price to decrease...", func() { -// initialGasPrice := gasPrice -// e2e.Eventually(func() bool { -// var err error -// gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) -// require.NoError(err) -// tests.Outf("{{blue}}.{{/}}") -// return initialGasPrice.Cmp(gasPrice) > 0 -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") -// tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) -// }) - -// ginkgo.By("sending funds at the current gas price", func() { -// // Create a recipient address -// recipientKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) -// recipientEthAddress := evm.GetEthAddress(recipientKey) - -// // Create transaction -// nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) -// require.NoError(err) -// tx := types.NewTx(&types.LegacyTx{ -// Nonce: nonce, -// GasPrice: gasPrice, -// Gas: e2e.DefaultGasLimit, -// To: &recipientEthAddress, -// Value: common.Big0, -// }) - -// // Send the transaction and wait for acceptance -// signedTx := sign(tx) -// _ = e2e.SendEthTransaction(ethClient, signedTx) -// }) - -// e2e.CheckBootstrapIsPossible(privateNetwork) -// }) -// }) +import ( + "math/big" + "strings" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/coreth/params" + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/tests" + "github.com/ava-labs/avalanchego/tests/fixture/e2e" + "github.com/ava-labs/avalanchego/tests/fixture/testnet" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" +) + +// This test uses the compiled bin for `hashing.sol` as +// well as its ABI contained in `hashing_contract.go`. + +var _ = e2e.DescribeCChain("[Dynamic Fees]", func() { + require := require.New(ginkgo.GinkgoT()) + + // Need a gas limit much larger than the standard 21_000 to enable + // the contract to induce a gas price increase + const largeGasLimit = uint64(8_000_000) + + // TODO(marun) What is the significance of this value? + gasTip := big.NewInt(1000 * params.GWei) + + ginkgo.It("should ensure that the gas price is affected by load", func() { + ginkgo.By("creating a new private network to ensure isolation from other tests") + privateNetwork := e2e.Env.NewPrivateNetwork() + + ginkgo.By("allocating a pre-funded key") + key := privateNetwork.GetConfig().FundedKeys[0] + ethAddress := evm.GetEthAddress(key) + + ginkgo.By("initializing a coreth client") + node := privateNetwork.GetNodes()[0] + nodeURI := testnet.NodeURI{ + NodeID: node.GetID(), + URI: node.GetProcessContext().URI, + } + ethClient := e2e.NewEthClient(nodeURI) + + ginkgo.By("initializing a transaction signer") + cChainID, err := ethClient.ChainID(e2e.DefaultContext()) + require.NoError(err) + signer := types.NewEIP155Signer(cChainID) + ecdsaKey := key.ToECDSA() + sign := func(tx *types.Transaction) *types.Transaction { + signedTx, err := types.SignTx(tx, signer, ecdsaKey) + require.NoError(err) + return signedTx + } + + var contractAddress common.Address + ginkgo.By("deploying an expensive contract", func() { + // Create transaction + nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) + require.NoError(err) + compiledContract := common.Hex2Bytes(hashingCompiledContract) + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + GasPrice: gasTip, + Gas: largeGasLimit, + Value: common.Big0, + Data: compiledContract, + }) + + // Send the transaction and wait for acceptance + signedTx := sign(tx) + receipt := e2e.SendEthTransaction(ethClient, signedTx) + + contractAddress = receipt.ContractAddress + }) + + var gasPrice *big.Int + ginkgo.By("calling the expensive contract repeatedly until a gas price increase is detected", func() { + // Evaluate the bytes representation of the contract + hashingABI, err := abi.JSON(strings.NewReader(hashingABIJson)) + require.NoError(err) + contractData, err := hashingABI.Pack("hashIt") + require.NoError(err) + + var initialGasPrice *big.Int + e2e.Eventually(func() bool { + // Check the gas price + var err error + gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) + require.NoError(err) + if initialGasPrice == nil { + initialGasPrice = gasPrice + tests.Outf("{{blue}}initial gas price is %v{{/}}\n", initialGasPrice) + } else if gasPrice.Cmp(initialGasPrice) > 0 { + // Gas price has increased + tests.Outf("{{blue}}gas price has increased to %v{{/}}\n", gasPrice) + return true + } + + // Create the transaction + nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) + require.NoError(err) + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + GasPrice: gasTip, + Gas: largeGasLimit, + To: &contractAddress, + Value: common.Big0, + Data: contractData, + }) + + // Send the transaction and wait for acceptance + signedTx := sign(tx) + _ = e2e.SendEthTransaction(ethClient, signedTx) + + // The gas price will be checked at the start of the next iteration + return false + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price increase before timeout") + }) + + ginkgo.By("waiting for the gas price to decrease...", func() { + initialGasPrice := gasPrice + e2e.Eventually(func() bool { + var err error + gasPrice, err = ethClient.SuggestGasPrice(e2e.DefaultContext()) + require.NoError(err) + tests.Outf("{{blue}}.{{/}}") + return initialGasPrice.Cmp(gasPrice) > 0 + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see gas price decrease before timeout") + tests.Outf("\n{{blue}}gas price has decreased to %v{{/}}\n", gasPrice) + }) + + ginkgo.By("sending funds at the current gas price", func() { + // Create a recipient address + recipientKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + recipientEthAddress := evm.GetEthAddress(recipientKey) + + // Create transaction + nonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), ethAddress) + require.NoError(err) + tx := types.NewTx(&types.LegacyTx{ + Nonce: nonce, + GasPrice: gasPrice, + Gas: e2e.DefaultGasLimit, + To: &recipientEthAddress, + Value: common.Big0, + }) + + // Send the transaction and wait for acceptance + signedTx := sign(tx) + _ = e2e.SendEthTransaction(ethClient, signedTx) + }) + + e2e.CheckBootstrapIsPossible(privateNetwork) + }) +}) diff --git a/tests/e2e/c/interchain_workflow.go b/tests/e2e/c/interchain_workflow.go index 8c019078ec6c..2c9bd198ec39 100644 --- a/tests/e2e/c/interchain_workflow.go +++ b/tests/e2e/c/interchain_workflow.go @@ -3,163 +3,163 @@ package c -// import ( -// "math/big" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/stretchr/testify/require" - -// "github.com/ava-labs/coreth/core/types" -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { -// require := require.New(ginkgo.GinkgoT()) - -// const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer - -// ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { -// ginkgo.By("initializing a new eth client") -// // Select a random node URI to use for both the eth client and -// // the wallet to avoid having to verify that all nodes are at -// // the same height before initializing the wallet. -// nodeURI := e2e.Env.GetRandomNodeURI() -// ethClient := e2e.NewEthClient(nodeURI) - -// ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") -// senderKey := e2e.Env.AllocateFundedKey() -// senderEthAddress := evm.GetEthAddress(senderKey) -// recipientKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) -// recipientEthAddress := evm.GetEthAddress(recipientKey) - -// ginkgo.By("sending funds from one address to another on the C-Chain", func() { -// // Create transaction -// acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) -// require.NoError(err) -// gasPrice := e2e.SuggestGasPrice(ethClient) -// tx := types.NewTransaction( -// acceptedNonce, -// recipientEthAddress, -// big.NewInt(int64(txAmount)), -// e2e.DefaultGasLimit, -// gasPrice, -// nil, -// ) - -// // Sign transaction -// cChainID, err := ethClient.ChainID(e2e.DefaultContext()) -// require.NoError(err) -// signer := types.NewEIP155Signer(cChainID) -// signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) -// require.NoError(err) - -// _ = e2e.SendEthTransaction(ethClient, signedTx) - -// ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") -// e2e.Eventually(func() bool { -// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) -// require.NoError(err) -// return balance.Cmp(big.NewInt(0)) > 0 -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") -// }) - -// // Wallet must be initialized after sending funds on the -// // C-Chain with the same node URI to ensure wallet state -// // matches on-chain state. -// ginkgo.By("initializing a keychain and associated wallet") -// keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) -// baseWallet := e2e.NewWallet(keychain, nodeURI) -// xWallet := baseWallet.X() -// cWallet := baseWallet.C() -// pWallet := baseWallet.P() - -// ginkgo.By("defining common configuration") -// avaxAssetID := xWallet.AVAXAssetID() -// // Use the same owner for import funds to X-Chain and P-Chain -// recipientOwner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// recipientKey.Address(), -// }, -// } -// // Use the same outputs for both X-Chain and P-Chain exports -// exportOutputs := []*secp256k1fx.TransferOutput{ -// { -// Amt: txAmount, -// OutputOwners: secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// keychain.Keys[0].Address(), -// }, -// }, -// }, -// } - -// ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { -// _, err := cWallet.IssueExportTx( -// xWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { -// _, err := xWallet.IssueImportTx( -// cWallet.BlockchainID(), -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { -// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { -// _, err := cWallet.IssueExportTx( -// constants.PlatformChainID, -// exportOutputs, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { -// _, err = pWallet.IssueImportTx( -// cWallet.BlockchainID(), -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { -// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) -// }) -// }) +import ( + "math/big" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/tests/fixture/e2e" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var _ = e2e.DescribeCChain("[Interchain Workflow]", func() { + require := require.New(ginkgo.GinkgoT()) + + const txAmount = 10 * units.Avax // Arbitrary amount to send and transfer + + ginkgo.It("should ensure that funds can be transferred from the C-Chain to the X-Chain and the P-Chain", func() { + ginkgo.By("initializing a new eth client") + // Select a random node URI to use for both the eth client and + // the wallet to avoid having to verify that all nodes are at + // the same height before initializing the wallet. + nodeURI := e2e.Env.GetRandomNodeURI() + ethClient := e2e.NewEthClient(nodeURI) + + ginkgo.By("allocating a pre-funded key to send from and a recipient key to deliver to") + senderKey := e2e.Env.AllocateFundedKey() + senderEthAddress := evm.GetEthAddress(senderKey) + recipientKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + recipientEthAddress := evm.GetEthAddress(recipientKey) + + ginkgo.By("sending funds from one address to another on the C-Chain", func() { + // Create transaction + acceptedNonce, err := ethClient.AcceptedNonceAt(e2e.DefaultContext(), senderEthAddress) + require.NoError(err) + gasPrice := e2e.SuggestGasPrice(ethClient) + tx := types.NewTransaction( + acceptedNonce, + recipientEthAddress, + big.NewInt(int64(txAmount)), + e2e.DefaultGasLimit, + gasPrice, + nil, + ) + + // Sign transaction + cChainID, err := ethClient.ChainID(e2e.DefaultContext()) + require.NoError(err) + signer := types.NewEIP155Signer(cChainID) + signedTx, err := types.SignTx(tx, signer, senderKey.ToECDSA()) + require.NoError(err) + + _ = e2e.SendEthTransaction(ethClient, signedTx) + + ginkgo.By("waiting for the C-Chain recipient address to have received the sent funds") + e2e.Eventually(func() bool { + balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) + require.NoError(err) + return balance.Cmp(big.NewInt(0)) > 0 + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see funds delivered before timeout") + }) + + // Wallet must be initialized after sending funds on the + // C-Chain with the same node URI to ensure wallet state + // matches on-chain state. + ginkgo.By("initializing a keychain and associated wallet") + keychain := secp256k1fx.NewKeychain(senderKey, recipientKey) + baseWallet := e2e.NewWallet(keychain, nodeURI) + xWallet := baseWallet.X() + cWallet := baseWallet.C() + pWallet := baseWallet.P() + + ginkgo.By("defining common configuration") + avaxAssetID := xWallet.AVAXAssetID() + // Use the same owner for import funds to X-Chain and P-Chain + recipientOwner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + recipientKey.Address(), + }, + } + // Use the same outputs for both X-Chain and P-Chain exports + exportOutputs := []*secp256k1fx.TransferOutput{ + { + Amt: txAmount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + keychain.Keys[0].Address(), + }, + }, + }, + } + + ginkgo.By("exporting AVAX from the C-Chain to the X-Chain", func() { + _, err := cWallet.IssueExportTx( + xWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the C-Chain to the X-Chain", func() { + _, err := xWallet.IssueImportTx( + cWallet.BlockchainID(), + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { + balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + ginkgo.By("exporting AVAX from the C-Chain to the P-Chain", func() { + _, err := cWallet.IssueExportTx( + constants.PlatformChainID, + exportOutputs, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the C-Chain to the P-Chain", func() { + _, err = pWallet.IssueImportTx( + cWallet.BlockchainID(), + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { + balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) + }) +}) diff --git a/tests/e2e/p/interchain_workflow.go b/tests/e2e/p/interchain_workflow.go index 33a8345f919f..44a6912715ef 100644 --- a/tests/e2e/p/interchain_workflow.go +++ b/tests/e2e/p/interchain_workflow.go @@ -3,225 +3,225 @@ package p -// import ( -// "math/big" -// "time" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/spf13/cast" - -// "github.com/stretchr/testify/require" - -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/api/info" -// "github.com/ava-labs/avalanchego/config" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/tests/fixture/testnet" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/platformvm/reward" -// "github.com/ava-labs/avalanchego/vms/platformvm/txs" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { -// require := require.New(ginkgo.GinkgoT()) - -// const ( -// transferAmount = 10 * units.Avax -// weight = 2_000 * units.Avax // Used for both validation and delegation -// ) - -// ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { -// network := e2e.Env.GetNetwork() - -// ginkgo.By("checking that the network has a compatible minimum stake duration", func() { -// minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) -// require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) -// }) - -// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") -// recipientKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) -// keychain := e2e.Env.NewKeychain(1) -// keychain.Add(recipientKey) -// nodeURI := e2e.Env.GetRandomNodeURI() -// baseWallet := e2e.NewWallet(keychain, nodeURI) -// xWallet := baseWallet.X() -// cWallet := baseWallet.C() -// pWallet := baseWallet.P() - -// ginkgo.By("defining common configuration") -// recipientEthAddress := evm.GetEthAddress(recipientKey) -// avaxAssetID := xWallet.AVAXAssetID() -// // Use the same owner for sending to X-Chain and importing funds to P-Chain -// recipientOwner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// recipientKey.Address(), -// }, -// } -// // Use the same outputs for both X-Chain and C-Chain exports -// exportOutputs := []*avax.TransferableOutput{ -// { -// Asset: avax.Asset{ -// ID: avaxAssetID, -// }, -// Out: &secp256k1fx.TransferOutput{ -// Amt: transferAmount, -// OutputOwners: secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// keychain.Keys[0].Address(), -// }, -// }, -// }, -// }, -// } - -// ginkgo.By("adding new node and waiting for it to report healthy") -// node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) -// e2e.WaitForHealthy(node) - -// ginkgo.By("retrieving new node's id and pop") -// infoClient := info.NewClient(node.GetProcessContext().URI) -// nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) -// require.NoError(err) - -// ginkgo.By("adding the new node as a validator", func() { -// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) -// // Validation duration doesn't actually matter to this -// // test - it is only ensuring that adding a validator -// // doesn't break interchain transfer. -// endTime := startTime.Add(30 * time.Second) - -// rewardKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) - -// const ( -// delegationPercent = 0.10 // 10% -// delegationShare = reward.PercentDenominator * delegationPercent -// ) - -// _, err = pWallet.IssueAddPermissionlessValidatorTx( -// &txs.SubnetValidator{ -// Validator: txs.Validator{ -// NodeID: nodeID, -// Start: uint64(startTime.Unix()), -// End: uint64(endTime.Unix()), -// Wght: weight, -// }, -// Subnet: constants.PrimaryNetworkID, -// }, -// nodePOP, -// pWallet.AVAXAssetID(), -// &secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{rewardKey.Address()}, -// }, -// &secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{rewardKey.Address()}, -// }, -// delegationShare, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("adding a delegator to the new node", func() { -// startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) -// // Delegation duration doesn't actually matter to this -// // test - it is only ensuring that adding a delegator -// // doesn't break interchain transfer. -// endTime := startTime.Add(15 * time.Second) - -// rewardKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) - -// _, err = pWallet.IssueAddPermissionlessDelegatorTx( -// &txs.SubnetValidator{ -// Validator: txs.Validator{ -// NodeID: nodeID, -// Start: uint64(startTime.Unix()), -// End: uint64(endTime.Unix()), -// Wght: weight, -// }, -// Subnet: constants.PrimaryNetworkID, -// }, -// pWallet.AVAXAssetID(), -// &secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{rewardKey.Address()}, -// }, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { -// _, err := pWallet.IssueExportTx( -// xWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { -// _, err := xWallet.IssueImportTx( -// constants.PlatformChainID, -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { -// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { -// _, err := pWallet.IssueExportTx( -// cWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("initializing a new eth client") -// ethClient := e2e.NewEthClient(nodeURI) - -// ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { -// _, err := cWallet.IssueImportTx( -// constants.PlatformChainID, -// recipientEthAddress, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") -// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) -// require.NoError(err) -// require.Positive(balance.Cmp(big.NewInt(0))) - -// ginkgo.By("stopping validator node to free up resources for a bootstrap check") -// require.NoError(node.Stop()) - -// e2e.CheckBootstrapIsPossible(network) -// }) -// }) +import ( + "math/big" + "time" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/spf13/cast" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/api/info" + "github.com/ava-labs/avalanchego/config" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/tests/fixture/e2e" + "github.com/ava-labs/avalanchego/tests/fixture/testnet" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/platformvm/reward" + "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var _ = e2e.DescribePChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { + require := require.New(ginkgo.GinkgoT()) + + const ( + transferAmount = 10 * units.Avax + weight = 2_000 * units.Avax // Used for both validation and delegation + ) + + ginkgo.It("should ensure that funds can be transferred from the P-Chain to the X-Chain and the C-Chain", func() { + network := e2e.Env.GetNetwork() + + ginkgo.By("checking that the network has a compatible minimum stake duration", func() { + minStakeDuration := cast.ToDuration(network.GetConfig().DefaultFlags[config.MinStakeDurationKey]) + require.Equal(testnet.DefaultMinStakeDuration, minStakeDuration) + }) + + ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") + recipientKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + keychain := e2e.Env.NewKeychain(1) + keychain.Add(recipientKey) + nodeURI := e2e.Env.GetRandomNodeURI() + baseWallet := e2e.NewWallet(keychain, nodeURI) + xWallet := baseWallet.X() + cWallet := baseWallet.C() + pWallet := baseWallet.P() + + ginkgo.By("defining common configuration") + recipientEthAddress := evm.GetEthAddress(recipientKey) + avaxAssetID := xWallet.AVAXAssetID() + // Use the same owner for sending to X-Chain and importing funds to P-Chain + recipientOwner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + recipientKey.Address(), + }, + } + // Use the same outputs for both X-Chain and C-Chain exports + exportOutputs := []*avax.TransferableOutput{ + { + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: transferAmount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + keychain.Keys[0].Address(), + }, + }, + }, + }, + } + + ginkgo.By("adding new node and waiting for it to report healthy") + node := e2e.AddEphemeralNode(network, testnet.FlagsMap{}) + e2e.WaitForHealthy(node) + + ginkgo.By("retrieving new node's id and pop") + infoClient := info.NewClient(node.GetProcessContext().URI) + nodeID, nodePOP, err := infoClient.GetNodeID(e2e.DefaultContext()) + require.NoError(err) + + ginkgo.By("adding the new node as a validator", func() { + startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) + // Validation duration doesn't actually matter to this + // test - it is only ensuring that adding a validator + // doesn't break interchain transfer. + endTime := startTime.Add(30 * time.Second) + + rewardKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + + const ( + delegationPercent = 0.10 // 10% + delegationShare = reward.PercentDenominator * delegationPercent + ) + + _, err = pWallet.IssueAddPermissionlessValidatorTx( + &txs.SubnetValidator{ + Validator: txs.Validator{ + NodeID: nodeID, + Start: uint64(startTime.Unix()), + End: uint64(endTime.Unix()), + Wght: weight, + }, + Subnet: constants.PrimaryNetworkID, + }, + nodePOP, + pWallet.AVAXAssetID(), + &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{rewardKey.Address()}, + }, + &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{rewardKey.Address()}, + }, + delegationShare, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("adding a delegator to the new node", func() { + startTime := time.Now().Add(e2e.DefaultValidatorStartTimeDiff) + // Delegation duration doesn't actually matter to this + // test - it is only ensuring that adding a delegator + // doesn't break interchain transfer. + endTime := startTime.Add(15 * time.Second) + + rewardKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + + _, err = pWallet.IssueAddPermissionlessDelegatorTx( + &txs.SubnetValidator{ + Validator: txs.Validator{ + NodeID: nodeID, + Start: uint64(startTime.Unix()), + End: uint64(endTime.Unix()), + Wght: weight, + }, + Subnet: constants.PrimaryNetworkID, + }, + pWallet.AVAXAssetID(), + &secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{rewardKey.Address()}, + }, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("exporting AVAX from the P-Chain to the X-Chain", func() { + _, err := pWallet.IssueExportTx( + xWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the P-Chain to the X-Chain", func() { + _, err := xWallet.IssueImportTx( + constants.PlatformChainID, + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the X-Chain", func() { + balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + ginkgo.By("exporting AVAX from the P-Chain to the C-Chain", func() { + _, err := pWallet.IssueExportTx( + cWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("initializing a new eth client") + ethClient := e2e.NewEthClient(nodeURI) + + ginkgo.By("importing AVAX from the P-Chain to the C-Chain", func() { + _, err := cWallet.IssueImportTx( + constants.PlatformChainID, + recipientEthAddress, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") + balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) + require.NoError(err) + require.Positive(balance.Cmp(big.NewInt(0))) + + ginkgo.By("stopping validator node to free up resources for a bootstrap check") + require.NoError(node.Stop()) + + e2e.CheckBootstrapIsPossible(network) + }) +}) diff --git a/tests/e2e/x/interchain_workflow.go b/tests/e2e/x/interchain_workflow.go index 99efca2eced0..f0c2951feb84 100644 --- a/tests/e2e/x/interchain_workflow.go +++ b/tests/e2e/x/interchain_workflow.go @@ -3,151 +3,151 @@ package x -// import ( -// "math/big" - -// ginkgo "github.com/onsi/ginkgo/v2" - -// "github.com/stretchr/testify/require" - -// "github.com/ava-labs/coreth/plugin/evm" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/tests/e2e" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { -// require := require.New(ginkgo.GinkgoT()) - -// const transferAmount = 10 * units.Avax - -// ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { -// nodeURI := e2e.Env.GetRandomNodeURI() - -// ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") -// recipientKey, err := secp256k1.NewPrivateKey() -// require.NoError(err) -// keychain := e2e.Env.NewKeychain(1) -// keychain.Add(recipientKey) -// baseWallet := e2e.NewWallet(keychain, nodeURI) -// xWallet := baseWallet.X() -// cWallet := baseWallet.C() -// pWallet := baseWallet.P() - -// ginkgo.By("defining common configuration") -// recipientEthAddress := evm.GetEthAddress(recipientKey) -// avaxAssetID := xWallet.AVAXAssetID() -// // Use the same owner for sending to X-Chain and importing funds to P-Chain -// recipientOwner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// recipientKey.Address(), -// }, -// } -// // Use the same outputs for both C-Chain and P-Chain exports -// exportOutputs := []*avax.TransferableOutput{ -// { -// Asset: avax.Asset{ -// ID: avaxAssetID, -// }, -// Out: &secp256k1fx.TransferOutput{ -// Amt: transferAmount, -// OutputOwners: secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// keychain.Keys[0].Address(), -// }, -// }, -// }, -// }, -// } - -// ginkgo.By("sending funds from one address to another on the X-Chain", func() { -// _, err = xWallet.IssueBaseTx( -// []*avax.TransferableOutput{{ -// Asset: avax.Asset{ -// ID: avaxAssetID, -// }, -// Out: &secp256k1fx.TransferOutput{ -// Amt: transferAmount, -// OutputOwners: recipientOwner, -// }, -// }}, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { -// balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { -// _, err := xWallet.IssueExportTx( -// cWallet.BlockchainID(), -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("initializing a new eth client") -// ethClient := e2e.NewEthClient(nodeURI) - -// ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { -// _, err := cWallet.IssueImportTx( -// xWallet.BlockchainID(), -// recipientEthAddress, -// e2e.WithDefaultContext(), -// e2e.WithSuggestedGasPrice(ethClient), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") -// e2e.Eventually(func() bool { -// balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) -// require.NoError(err) -// return balance.Cmp(big.NewInt(0)) > 0 -// }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") - -// ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { -// _, err := xWallet.IssueExportTx( -// constants.PlatformChainID, -// exportOutputs, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { -// _, err := pWallet.IssueImportTx( -// xWallet.BlockchainID(), -// &recipientOwner, -// e2e.WithDefaultContext(), -// ) -// require.NoError(err) -// }) - -// ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { -// balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( -// recipientKey.Address(), -// ))) -// require.NoError(err) -// require.Positive(balances[avaxAssetID]) -// }) - -// e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) -// }) -// }) +import ( + "math/big" + + ginkgo "github.com/onsi/ginkgo/v2" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/tests/fixture/e2e" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var _ = e2e.DescribeXChain("[Interchain Workflow]", ginkgo.Label(e2e.UsesCChainLabel), func() { + require := require.New(ginkgo.GinkgoT()) + + const transferAmount = 10 * units.Avax + + ginkgo.It("should ensure that funds can be transferred from the X-Chain to the C-Chain and the P-Chain", func() { + nodeURI := e2e.Env.GetRandomNodeURI() + + ginkgo.By("creating wallet with a funded key to send from and recipient key to deliver to") + recipientKey, err := secp256k1.NewPrivateKey() + require.NoError(err) + keychain := e2e.Env.NewKeychain(1) + keychain.Add(recipientKey) + baseWallet := e2e.NewWallet(keychain, nodeURI) + xWallet := baseWallet.X() + cWallet := baseWallet.C() + pWallet := baseWallet.P() + + ginkgo.By("defining common configuration") + recipientEthAddress := evm.GetEthAddress(recipientKey) + avaxAssetID := xWallet.AVAXAssetID() + // Use the same owner for sending to X-Chain and importing funds to P-Chain + recipientOwner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + recipientKey.Address(), + }, + } + // Use the same outputs for both C-Chain and P-Chain exports + exportOutputs := []*avax.TransferableOutput{ + { + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: transferAmount, + OutputOwners: secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + keychain.Keys[0].Address(), + }, + }, + }, + }, + } + + ginkgo.By("sending funds from one address to another on the X-Chain", func() { + _, err = xWallet.IssueBaseTx( + []*avax.TransferableOutput{{ + Asset: avax.Asset{ + ID: avaxAssetID, + }, + Out: &secp256k1fx.TransferOutput{ + Amt: transferAmount, + OutputOwners: recipientOwner, + }, + }}, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the X-Chain recipient address has received the sent funds", func() { + balances, err := xWallet.Builder().GetFTBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + ginkgo.By("exporting AVAX from the X-Chain to the C-Chain", func() { + _, err := xWallet.IssueExportTx( + cWallet.BlockchainID(), + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("initializing a new eth client") + ethClient := e2e.NewEthClient(nodeURI) + + ginkgo.By("importing AVAX from the X-Chain to the C-Chain", func() { + _, err := cWallet.IssueImportTx( + xWallet.BlockchainID(), + recipientEthAddress, + e2e.WithDefaultContext(), + e2e.WithSuggestedGasPrice(ethClient), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the C-Chain") + e2e.Eventually(func() bool { + balance, err := ethClient.BalanceAt(e2e.DefaultContext(), recipientEthAddress, nil) + require.NoError(err) + return balance.Cmp(big.NewInt(0)) > 0 + }, e2e.DefaultTimeout, e2e.DefaultPollingInterval, "failed to see recipient address funded before timeout") + + ginkgo.By("exporting AVAX from the X-Chain to the P-Chain", func() { + _, err := xWallet.IssueExportTx( + constants.PlatformChainID, + exportOutputs, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("importing AVAX from the X-Chain to the P-Chain", func() { + _, err := pWallet.IssueImportTx( + xWallet.BlockchainID(), + &recipientOwner, + e2e.WithDefaultContext(), + ) + require.NoError(err) + }) + + ginkgo.By("checking that the recipient address has received imported funds on the P-Chain", func() { + balances, err := pWallet.Builder().GetBalance(common.WithCustomAddresses(set.Of( + recipientKey.Address(), + ))) + require.NoError(err) + require.Positive(balances[avaxAssetID]) + }) + + e2e.CheckBootstrapIsPossible(e2e.Env.GetNetwork()) + }) +}) diff --git a/tests/fixture/e2e/helpers.go b/tests/fixture/e2e/helpers.go index 206da6e41398..15da611324e0 100644 --- a/tests/fixture/e2e/helpers.go +++ b/tests/fixture/e2e/helpers.go @@ -16,6 +16,10 @@ import ( "github.com/stretchr/testify/require" + "github.com/ava-labs/coreth/core/types" + "github.com/ava-labs/coreth/ethclient" + "github.com/ava-labs/coreth/interfaces" + "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/tests" "github.com/ava-labs/avalanchego/tests/fixture/testnet" @@ -63,7 +67,7 @@ func NewWallet(keychain *secp256k1fx.Keychain, nodeURI testnet.NodeURI) primary. baseWallet, err := primary.MakeWallet(DefaultContext(), &primary.WalletConfig{ URI: nodeURI.URI, AVAXKeychain: keychain, - // EthKeychain: keychain, + EthKeychain: keychain, }) require.NoError(ginkgo.GinkgoT(), err) return primary.NewWalletWithOptions( @@ -76,15 +80,15 @@ func NewWallet(keychain *secp256k1fx.Keychain, nodeURI testnet.NodeURI) primary. ) } -// // Create a new eth client targeting the specified node URI. -// func NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { -// tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) -// nodeAddress := strings.Split(nodeURI.URI, "//")[1] -// uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) -// client, err := ethclient.Dial(uri) -// require.NoError(ginkgo.GinkgoT(), err) -// return client -// } +// Create a new eth client targeting the specified node URI. +func NewEthClient(nodeURI testnet.NodeURI) ethclient.Client { + tests.Outf("{{blue}} initializing a new eth client for node %s with URI: %s {{/}}\n", nodeURI.NodeID, nodeURI.URI) + nodeAddress := strings.Split(nodeURI.URI, "//")[1] + uri := fmt.Sprintf("ws://%s/ext/bc/C/ws", nodeAddress) + client, err := ethclient.Dial(uri) + require.NoError(ginkgo.GinkgoT(), err) + return client +} // Helper simplifying use of a timed context by canceling the context on ginkgo teardown. func ContextWithTimeout(duration time.Duration) context.Context { @@ -148,49 +152,49 @@ func WaitForHealthy(node testnet.Node) { require.NoError(ginkgo.GinkgoT(), testnet.WaitForHealthy(ctx, node)) } -// // Sends an eth transaction, waits for the transaction receipt to be issued -// // and checks that the receipt indicates success. -// func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { -// require := require.New(ginkgo.GinkgoT()) - -// txID := signedTx.Hash() -// tests.Outf(" sending eth transaction with ID: %s\n", txID) - -// require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) - -// // Wait for the receipt -// var receipt *types.Receipt -// Eventually(func() bool { -// var err error -// receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) -// if errors.Is(err, interfaces.NotFound) { -// return false // Transaction is still pending -// } -// require.NoError(err) -// return true -// }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") - -// require.Equal(receipt.Status, types.ReceiptStatusSuccessful) -// return receipt -// } - -// // Determines the suggested gas price for the configured client that will -// // maximize the chances of transaction acceptance. -// func SuggestGasPrice(ethClient ethclient.Client) *big.Int { -// gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) -// require.NoError(ginkgo.GinkgoT(), err) -// // Double the suggested gas price to maximize the chances of -// // acceptance. Maybe this can be revisited pending resolution of -// // https://github.com/ava-labs/coreth/issues/314. -// gasPrice.Add(gasPrice, gasPrice) -// return gasPrice -// } - -// // Helper simplifying use via an option of a gas price appropriate for testing. -// func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { -// baseFee := SuggestGasPrice(ethClient) -// return common.WithBaseFee(baseFee) -// } +// Sends an eth transaction, waits for the transaction receipt to be issued +// and checks that the receipt indicates success. +func SendEthTransaction(ethClient ethclient.Client, signedTx *types.Transaction) *types.Receipt { + require := require.New(ginkgo.GinkgoT()) + + txID := signedTx.Hash() + tests.Outf(" sending eth transaction with ID: %s\n", txID) + + require.NoError(ethClient.SendTransaction(DefaultContext(), signedTx)) + + // Wait for the receipt + var receipt *types.Receipt + Eventually(func() bool { + var err error + receipt, err = ethClient.TransactionReceipt(DefaultContext(), txID) + if errors.Is(err, interfaces.NotFound) { + return false // Transaction is still pending + } + require.NoError(err) + return true + }, DefaultTimeout, DefaultPollingInterval, "failed to see transaction acceptance before timeout") + + require.Equal(receipt.Status, types.ReceiptStatusSuccessful) + return receipt +} + +// Determines the suggested gas price for the configured client that will +// maximize the chances of transaction acceptance. +func SuggestGasPrice(ethClient ethclient.Client) *big.Int { + gasPrice, err := ethClient.SuggestGasPrice(DefaultContext()) + require.NoError(ginkgo.GinkgoT(), err) + // Double the suggested gas price to maximize the chances of + // acceptance. Maybe this can be revisited pending resolution of + // https://github.com/ava-labs/coreth/issues/314. + gasPrice.Add(gasPrice, gasPrice) + return gasPrice +} + +// Helper simplifying use via an option of a gas price appropriate for testing. +func WithSuggestedGasPrice(ethClient ethclient.Client) common.Option { + baseFee := SuggestGasPrice(ethClient) + return common.WithBaseFee(baseFee) +} // Verify that a new node can bootstrap into the network. func CheckBootstrapIsPossible(network testnet.Network) { diff --git a/tests/fixture/testnet/config.go b/tests/fixture/testnet/config.go index 6c82db1a420f..425aa646a690 100644 --- a/tests/fixture/testnet/config.go +++ b/tests/fixture/testnet/config.go @@ -15,6 +15,10 @@ import ( "github.com/spf13/cast" + "github.com/ava-labs/coreth/core" + "github.com/ava-labs/coreth/params" + "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/avalanchego/config" "github.com/ava-labs/avalanchego/genesis" "github.com/ava-labs/avalanchego/ids" @@ -139,15 +143,15 @@ func (c *NetworkConfig) EnsureGenesis(networkID uint32, validatorIDs []ids.NodeI // Ensure pre-funded keys have arbitrary large balances on both chains to support testing xChainBalances := make(XChainBalanceMap, len(c.FundedKeys)) - // cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) - // for _, key := range c.FundedKeys { - // xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount - // cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ - // Balance: DefaultFundedKeyCChainAmount, - // } - // } - - genesis, err := NewTestGenesis(networkID, xChainBalances /*, cChainBalances*/, validatorIDs) + cChainBalances := make(core.GenesisAlloc, len(c.FundedKeys)) + for _, key := range c.FundedKeys { + xChainBalances[key.Address()] = DefaultFundedKeyXChainAmount + cChainBalances[evm.GetEthAddress(key)] = core.GenesisAccount{ + Balance: DefaultFundedKeyCChainAmount, + } + } + + genesis, err := NewTestGenesis(networkID, xChainBalances, cChainBalances, validatorIDs) if err != nil { return err } @@ -307,7 +311,7 @@ type XChainBalanceMap map[ids.ShortID]uint64 func NewTestGenesis( networkID uint32, xChainBalances XChainBalanceMap, - // cChainBalances core.GenesisAlloc, + cChainBalances core.GenesisAlloc, validatorIDs []ids.NodeID, ) (*genesis.UnparsedConfig, error) { // Validate inputs @@ -318,7 +322,7 @@ func NewTestGenesis( if len(validatorIDs) == 0 { return nil, errMissingValidatorsForGenesis } - if len(xChainBalances) == 0 /*|| len(cChainBalances) == 0*/ { + if len(xChainBalances) == 0 || len(cChainBalances) == 0 { return nil, errMissingBalancesForGenesis } @@ -390,20 +394,20 @@ func NewTestGenesis( ) } - // // Define C-Chain genesis - // cChainGenesis := &core.Genesis{ - // Config: ¶ms.ChainConfig{ - // ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary - // }, - // Difficulty: big.NewInt(0), // Difficulty is a mandatory field - // GasLimit: DefaultGasLimit, - // Alloc: cChainBalances, - // } - // cChainGenesisBytes, err := json.Marshal(cChainGenesis) - // if err != nil { - // return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) - // } - // config.CChainGenesis = string(cChainGenesisBytes) + // Define C-Chain genesis + cChainGenesis := &core.Genesis{ + Config: ¶ms.ChainConfig{ + ChainID: big.NewInt(43112), // Arbitrary chain ID is arbitrary + }, + Difficulty: big.NewInt(0), // Difficulty is a mandatory field + GasLimit: DefaultGasLimit, + Alloc: cChainBalances, + } + cChainGenesisBytes, err := json.Marshal(cChainGenesis) + if err != nil { + return nil, fmt.Errorf("failed to marshal C-Chain genesis: %w", err) + } + config.CChainGenesis = string(cChainGenesisBytes) // Give staking rewards for initial validators to a random address. Any testing of staking rewards // will be easier to perform with nodes other than the initial validators since the timing of diff --git a/vms/example/xsvm/cmd/chain/create/cmd.go b/vms/example/xsvm/cmd/chain/create/cmd.go index 043b4298dcdf..1f00491a4ce6 100644 --- a/vms/example/xsvm/cmd/chain/create/cmd.go +++ b/vms/example/xsvm/cmd/chain/create/cmd.go @@ -42,9 +42,9 @@ func createFunc(c *cobra.Command, args []string) error { // that [uri] is hosting. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: config.URI, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: config.URI, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(config.SubnetID), }) if err != nil { diff --git a/wallet/chain/c/backend.go b/wallet/chain/c/backend.go index b88c8c643bc3..0a735116b646 100644 --- a/wallet/chain/c/backend.go +++ b/wallet/chain/c/backend.go @@ -3,153 +3,153 @@ package c -// import ( -// "errors" -// "fmt" -// "math/big" -// "sync" - -// stdcontext "context" - -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/database" -// "github.com/ava-labs/avalanchego/utils/math" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var ( -// _ Backend = (*backend)(nil) - -// errUnknownTxType = errors.New("unknown tx type") -// ) - -// // Backend defines the full interface required to support a C-chain wallet. -// type Backend interface { -// common.ChainUTXOs -// BuilderBackend -// SignerBackend - -// AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error -// } - -// type backend struct { -// Context -// common.ChainUTXOs - -// accountsLock sync.RWMutex -// accounts map[ethcommon.Address]*Account -// } - -// type Account struct { -// Balance *big.Int -// Nonce uint64 -// } - -// func NewBackend( -// ctx Context, -// utxos common.ChainUTXOs, -// accounts map[ethcommon.Address]*Account, -// ) Backend { -// return &backend{ -// Context: ctx, -// ChainUTXOs: utxos, -// accounts: accounts, -// } -// } - -// func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { -// switch tx := tx.UnsignedAtomicTx.(type) { -// case *evm.UnsignedImportTx: -// for _, input := range tx.ImportedInputs { -// utxoID := input.InputID() -// if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { -// return err -// } -// } - -// b.accountsLock.Lock() -// defer b.accountsLock.Unlock() - -// for _, output := range tx.Outs { -// account, ok := b.accounts[output.Address] -// if !ok { -// continue -// } - -// balance := new(big.Int).SetUint64(output.Amount) -// balance.Mul(balance, avaxConversionRate) -// account.Balance.Add(account.Balance, balance) -// } -// case *evm.UnsignedExportTx: -// txID := tx.ID() -// for i, out := range tx.ExportedOutputs { -// err := b.AddUTXO( -// ctx, -// tx.DestinationChain, -// &avax.UTXO{ -// UTXOID: avax.UTXOID{ -// TxID: txID, -// OutputIndex: uint32(i), -// }, -// Asset: avax.Asset{ID: out.AssetID()}, -// Out: out.Out, -// }, -// ) -// if err != nil { -// return err -// } -// } - -// b.accountsLock.Lock() -// defer b.accountsLock.Unlock() - -// for _, input := range tx.Ins { -// account, ok := b.accounts[input.Address] -// if !ok { -// continue -// } - -// balance := new(big.Int).SetUint64(input.Amount) -// balance.Mul(balance, avaxConversionRate) -// if account.Balance.Cmp(balance) == -1 { -// return errInsufficientFunds -// } -// account.Balance.Sub(account.Balance, balance) - -// newNonce, err := math.Add64(input.Nonce, 1) -// if err != nil { -// return err -// } -// account.Nonce = newNonce -// } -// default: -// return fmt.Errorf("%w: %T", errUnknownTxType, tx) -// } -// return nil -// } - -// func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { -// b.accountsLock.RLock() -// defer b.accountsLock.RUnlock() - -// account, exists := b.accounts[addr] -// if !exists { -// return nil, database.ErrNotFound -// } -// return account.Balance, nil -// } - -// func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { -// b.accountsLock.RLock() -// defer b.accountsLock.RUnlock() - -// account, exists := b.accounts[addr] -// if !exists { -// return 0, database.ErrNotFound -// } -// return account.Nonce, nil -// } +import ( + "errors" + "fmt" + "math/big" + "sync" + + stdcontext "context" + + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/utils/math" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var ( + _ Backend = (*backend)(nil) + + errUnknownTxType = errors.New("unknown tx type") +) + +// Backend defines the full interface required to support a C-chain wallet. +type Backend interface { + common.ChainUTXOs + BuilderBackend + SignerBackend + + AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error +} + +type backend struct { + Context + common.ChainUTXOs + + accountsLock sync.RWMutex + accounts map[ethcommon.Address]*Account +} + +type Account struct { + Balance *big.Int + Nonce uint64 +} + +func NewBackend( + ctx Context, + utxos common.ChainUTXOs, + accounts map[ethcommon.Address]*Account, +) Backend { + return &backend{ + Context: ctx, + ChainUTXOs: utxos, + accounts: accounts, + } +} + +func (b *backend) AcceptAtomicTx(ctx stdcontext.Context, tx *evm.Tx) error { + switch tx := tx.UnsignedAtomicTx.(type) { + case *evm.UnsignedImportTx: + for _, input := range tx.ImportedInputs { + utxoID := input.InputID() + if err := b.RemoveUTXO(ctx, tx.SourceChain, utxoID); err != nil { + return err + } + } + + b.accountsLock.Lock() + defer b.accountsLock.Unlock() + + for _, output := range tx.Outs { + account, ok := b.accounts[output.Address] + if !ok { + continue + } + + balance := new(big.Int).SetUint64(output.Amount) + balance.Mul(balance, avaxConversionRate) + account.Balance.Add(account.Balance, balance) + } + case *evm.UnsignedExportTx: + txID := tx.ID() + for i, out := range tx.ExportedOutputs { + err := b.AddUTXO( + ctx, + tx.DestinationChain, + &avax.UTXO{ + UTXOID: avax.UTXOID{ + TxID: txID, + OutputIndex: uint32(i), + }, + Asset: avax.Asset{ID: out.AssetID()}, + Out: out.Out, + }, + ) + if err != nil { + return err + } + } + + b.accountsLock.Lock() + defer b.accountsLock.Unlock() + + for _, input := range tx.Ins { + account, ok := b.accounts[input.Address] + if !ok { + continue + } + + balance := new(big.Int).SetUint64(input.Amount) + balance.Mul(balance, avaxConversionRate) + if account.Balance.Cmp(balance) == -1 { + return errInsufficientFunds + } + account.Balance.Sub(account.Balance, balance) + + newNonce, err := math.Add64(input.Nonce, 1) + if err != nil { + return err + } + account.Nonce = newNonce + } + default: + return fmt.Errorf("%w: %T", errUnknownTxType, tx) + } + return nil +} + +func (b *backend) Balance(_ stdcontext.Context, addr ethcommon.Address) (*big.Int, error) { + b.accountsLock.RLock() + defer b.accountsLock.RUnlock() + + account, exists := b.accounts[addr] + if !exists { + return nil, database.ErrNotFound + } + return account.Balance, nil +} + +func (b *backend) Nonce(_ stdcontext.Context, addr ethcommon.Address) (uint64, error) { + b.accountsLock.RLock() + defer b.accountsLock.RUnlock() + + account, exists := b.accounts[addr] + if !exists { + return 0, database.ErrNotFound + } + return account.Nonce, nil +} diff --git a/wallet/chain/c/builder.go b/wallet/chain/c/builder.go index c51d2647777e..d2d088e88a53 100644 --- a/wallet/chain/c/builder.go +++ b/wallet/chain/c/builder.go @@ -3,399 +3,399 @@ package c -// import ( -// "errors" -// "math/big" - -// stdcontext "context" - -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils" -// "github.com/ava-labs/avalanchego/utils/math" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// const avaxConversionRateInt = 1_000_000_000 - -// var ( -// _ Builder = (*builder)(nil) - -// errInsufficientFunds = errors.New("insufficient funds") - -// // avaxConversionRate is the conversion rate between the smallest -// // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest -// // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. -// // -// // This is only required for AVAX because the denomination of 1 AVAX is 9 -// // decimal places on the X and P chains, but is 18 decimal places within the -// // EVM. -// avaxConversionRate = big.NewInt(avaxConversionRateInt) -// ) - -// // Builder provides a convenient interface for building unsigned C-chain -// // transactions. -// type Builder interface { -// // GetBalance calculates the amount of AVAX that this builder has control -// // over. -// GetBalance( -// options ...common.Option, -// ) (*big.Int, error) - -// // GetImportableBalance calculates the amount of AVAX that this builder -// // could import from the provided chain. -// // -// // - [chainID] specifies the chain the funds are from. -// GetImportableBalance( -// chainID ids.ID, -// options ...common.Option, -// ) (uint64, error) - -// // NewImportTx creates an import transaction that attempts to consume all -// // the available UTXOs and import the funds to [to]. -// // -// // - [chainID] specifies the chain to be importing funds from. -// // - [to] specifies where to send the imported funds to. -// // - [baseFee] specifies the fee price willing to be paid by this tx. -// NewImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedImportTx, error) - -// // NewExportTx creates an export transaction that attempts to send all the -// // provided [outputs] to the requested [chainID]. -// // -// // - [chainID] specifies the chain to be exporting the funds to. -// // - [outputs] specifies the outputs to send to the [chainID]. -// // - [baseFee] specifies the fee price willing to be paid by this tx. -// NewExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedExportTx, error) -// } - -// // BuilderBackend specifies the required information needed to build unsigned -// // C-chain transactions. -// type BuilderBackend interface { -// Context - -// UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) -// Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) -// Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) -// } - -// type builder struct { -// avaxAddrs set.Set[ids.ShortID] -// ethAddrs set.Set[ethcommon.Address] -// backend BuilderBackend -// } - -// // NewBuilder returns a new transaction builder. -// // -// // - [avaxAddrs] is the set of addresses in the AVAX format that the builder -// // assumes can be used when signing the transactions in the future. -// // - [ethAddrs] is the set of addresses in the Eth format that the builder -// // assumes can be used when signing the transactions in the future. -// // - [backend] provides the required access to the chain's context and state -// // to build out the transactions. -// func NewBuilder( -// avaxAddrs set.Set[ids.ShortID], -// ethAddrs set.Set[ethcommon.Address], -// backend BuilderBackend, -// ) Builder { -// return &builder{ -// avaxAddrs: avaxAddrs, -// ethAddrs: ethAddrs, -// backend: backend, -// } -// } - -// func (b *builder) GetBalance( -// options ...common.Option, -// ) (*big.Int, error) { -// var ( -// ops = common.NewOptions(options) -// ctx = ops.Context() -// addrs = ops.EthAddresses(b.ethAddrs) -// totalBalance = new(big.Int) -// ) -// for addr := range addrs { -// balance, err := b.backend.Balance(ctx, addr) -// if err != nil { -// return nil, err -// } -// totalBalance.Add(totalBalance, balance) -// } - -// return totalBalance, nil -// } - -// func (b *builder) GetImportableBalance( -// chainID ids.ID, -// options ...common.Option, -// ) (uint64, error) { -// ops := common.NewOptions(options) -// utxos, err := b.backend.UTXOs(ops.Context(), chainID) -// if err != nil { -// return 0, err -// } - -// var ( -// addrs = ops.Addresses(b.avaxAddrs) -// minIssuanceTime = ops.MinIssuanceTime() -// avaxAssetID = b.backend.AVAXAssetID() -// balance uint64 -// ) -// for _, utxo := range utxos { -// amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) -// if !ok { -// continue -// } - -// newBalance, err := math.Add64(balance, amount) -// if err != nil { -// return 0, err -// } -// balance = newBalance -// } - -// return balance, nil -// } - -// func (b *builder) NewImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedImportTx, error) { -// ops := common.NewOptions(options) -// utxos, err := b.backend.UTXOs(ops.Context(), chainID) -// if err != nil { -// return nil, err -// } - -// var ( -// addrs = ops.Addresses(b.avaxAddrs) -// minIssuanceTime = ops.MinIssuanceTime() -// avaxAssetID = b.backend.AVAXAssetID() - -// importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) -// importedAmount uint64 -// ) -// for _, utxo := range utxos { -// amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) -// if !ok { -// continue -// } - -// importedInputs = append(importedInputs, &avax.TransferableInput{ -// UTXOID: utxo.UTXOID, -// Asset: utxo.Asset, -// In: &secp256k1fx.TransferInput{ -// Amt: amount, -// Input: secp256k1fx.Input{ -// SigIndices: inputSigIndices, -// }, -// }, -// }) - -// newImportedAmount, err := math.Add64(importedAmount, amount) -// if err != nil { -// return nil, err -// } -// importedAmount = newImportedAmount -// } - -// utils.Sort(importedInputs) -// tx := &evm.UnsignedImportTx{ -// NetworkID: b.backend.NetworkID(), -// BlockchainID: b.backend.BlockchainID(), -// SourceChain: chainID, -// ImportedInputs: importedInputs, -// } - -// // We must initialize the bytes of the tx to calculate the initial cost -// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} -// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { -// return nil, err -// } - -// gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) -// if err != nil { -// return nil, err -// } -// gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas - -// txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) -// if err != nil { -// return nil, err -// } - -// if importedAmount <= txFee { -// return nil, errInsufficientFunds -// } - -// tx.Outs = []evm.EVMOutput{{ -// Address: to, -// Amount: importedAmount - txFee, -// AssetID: avaxAssetID, -// }} -// return tx, nil -// } - -// func (b *builder) NewExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedExportTx, error) { -// var ( -// avaxAssetID = b.backend.AVAXAssetID() -// exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) -// exportedAmount uint64 -// ) -// for i, output := range outputs { -// exportedOutputs[i] = &avax.TransferableOutput{ -// Asset: avax.Asset{ID: avaxAssetID}, -// Out: output, -// } - -// newExportedAmount, err := math.Add64(exportedAmount, output.Amt) -// if err != nil { -// return nil, err -// } -// exportedAmount = newExportedAmount -// } - -// avax.SortTransferableOutputs(exportedOutputs, evm.Codec) -// tx := &evm.UnsignedExportTx{ -// NetworkID: b.backend.NetworkID(), -// BlockchainID: b.backend.BlockchainID(), -// DestinationChain: chainID, -// ExportedOutputs: exportedOutputs, -// } - -// // We must initialize the bytes of the tx to calculate the initial cost -// wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} -// if err := wrappedTx.Sign(evm.Codec, nil); err != nil { -// return nil, err -// } - -// cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) -// if err != nil { -// return nil, err -// } - -// initialFee, err := evm.CalculateDynamicFee(cost, baseFee) -// if err != nil { -// return nil, err -// } - -// amountToConsume, err := math.Add64(exportedAmount, initialFee) -// if err != nil { -// return nil, err -// } - -// var ( -// ops = common.NewOptions(options) -// ctx = ops.Context() -// addrs = ops.EthAddresses(b.ethAddrs) -// inputs = make([]evm.EVMInput, 0, addrs.Len()) -// ) -// for addr := range addrs { -// if amountToConsume == 0 { -// break -// } - -// prevFee, err := evm.CalculateDynamicFee(cost, baseFee) -// if err != nil { -// return nil, err -// } - -// newCost := cost + evm.EVMInputGas -// newFee, err := evm.CalculateDynamicFee(newCost, baseFee) -// if err != nil { -// return nil, err -// } - -// additionalFee := newFee - prevFee - -// balance, err := b.backend.Balance(ctx, addr) -// if err != nil { -// return nil, err -// } - -// // Since the asset is AVAX, we divide by the avaxConversionRate to -// // convert back to the correct denomination of AVAX that can be -// // exported. -// avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() - -// // If the balance for [addr] is insufficient to cover the additional -// // cost of adding an input to the transaction, skip adding the input -// // altogether. -// if avaxBalance <= additionalFee { -// continue -// } - -// // Update the cost for the next iteration -// cost = newCost - -// amountToConsume, err = math.Add64(amountToConsume, additionalFee) -// if err != nil { -// return nil, err -// } - -// nonce, err := b.backend.Nonce(ctx, addr) -// if err != nil { -// return nil, err -// } - -// inputAmount := math.Min(amountToConsume, avaxBalance) -// inputs = append(inputs, evm.EVMInput{ -// Address: addr, -// Amount: inputAmount, -// AssetID: avaxAssetID, -// Nonce: nonce, -// }) -// amountToConsume -= inputAmount -// } - -// if amountToConsume > 0 { -// return nil, errInsufficientFunds -// } - -// utils.Sort(inputs) -// tx.Ins = inputs -// return tx, nil -// } - -// func getSpendableAmount( -// utxo *avax.UTXO, -// addrs set.Set[ids.ShortID], -// minIssuanceTime uint64, -// avaxAssetID ids.ID, -// ) (uint64, []uint32, bool) { -// if utxo.Asset.ID != avaxAssetID { -// // Only AVAX can be imported -// return 0, nil, false -// } - -// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) -// if !ok { -// // Can't import an unknown transfer output type -// return 0, nil, false -// } - -// inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) -// return out.Amt, inputSigIndices, ok -// } +import ( + "errors" + "math/big" + + stdcontext "context" + + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils" + "github.com/ava-labs/avalanchego/utils/math" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +const avaxConversionRateInt = 1_000_000_000 + +var ( + _ Builder = (*builder)(nil) + + errInsufficientFunds = errors.New("insufficient funds") + + // avaxConversionRate is the conversion rate between the smallest + // denomination on the X-Chain and P-chain, 1 nAVAX, and the smallest + // denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei. + // + // This is only required for AVAX because the denomination of 1 AVAX is 9 + // decimal places on the X and P chains, but is 18 decimal places within the + // EVM. + avaxConversionRate = big.NewInt(avaxConversionRateInt) +) + +// Builder provides a convenient interface for building unsigned C-chain +// transactions. +type Builder interface { + // GetBalance calculates the amount of AVAX that this builder has control + // over. + GetBalance( + options ...common.Option, + ) (*big.Int, error) + + // GetImportableBalance calculates the amount of AVAX that this builder + // could import from the provided chain. + // + // - [chainID] specifies the chain the funds are from. + GetImportableBalance( + chainID ids.ID, + options ...common.Option, + ) (uint64, error) + + // NewImportTx creates an import transaction that attempts to consume all + // the available UTXOs and import the funds to [to]. + // + // - [chainID] specifies the chain to be importing funds from. + // - [to] specifies where to send the imported funds to. + // - [baseFee] specifies the fee price willing to be paid by this tx. + NewImportTx( + chainID ids.ID, + to ethcommon.Address, + baseFee *big.Int, + options ...common.Option, + ) (*evm.UnsignedImportTx, error) + + // NewExportTx creates an export transaction that attempts to send all the + // provided [outputs] to the requested [chainID]. + // + // - [chainID] specifies the chain to be exporting the funds to. + // - [outputs] specifies the outputs to send to the [chainID]. + // - [baseFee] specifies the fee price willing to be paid by this tx. + NewExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + baseFee *big.Int, + options ...common.Option, + ) (*evm.UnsignedExportTx, error) +} + +// BuilderBackend specifies the required information needed to build unsigned +// C-chain transactions. +type BuilderBackend interface { + Context + + UTXOs(ctx stdcontext.Context, sourceChainID ids.ID) ([]*avax.UTXO, error) + Balance(ctx stdcontext.Context, addr ethcommon.Address) (*big.Int, error) + Nonce(ctx stdcontext.Context, addr ethcommon.Address) (uint64, error) +} + +type builder struct { + avaxAddrs set.Set[ids.ShortID] + ethAddrs set.Set[ethcommon.Address] + backend BuilderBackend +} + +// NewBuilder returns a new transaction builder. +// +// - [avaxAddrs] is the set of addresses in the AVAX format that the builder +// assumes can be used when signing the transactions in the future. +// - [ethAddrs] is the set of addresses in the Eth format that the builder +// assumes can be used when signing the transactions in the future. +// - [backend] provides the required access to the chain's context and state +// to build out the transactions. +func NewBuilder( + avaxAddrs set.Set[ids.ShortID], + ethAddrs set.Set[ethcommon.Address], + backend BuilderBackend, +) Builder { + return &builder{ + avaxAddrs: avaxAddrs, + ethAddrs: ethAddrs, + backend: backend, + } +} + +func (b *builder) GetBalance( + options ...common.Option, +) (*big.Int, error) { + var ( + ops = common.NewOptions(options) + ctx = ops.Context() + addrs = ops.EthAddresses(b.ethAddrs) + totalBalance = new(big.Int) + ) + for addr := range addrs { + balance, err := b.backend.Balance(ctx, addr) + if err != nil { + return nil, err + } + totalBalance.Add(totalBalance, balance) + } + + return totalBalance, nil +} + +func (b *builder) GetImportableBalance( + chainID ids.ID, + options ...common.Option, +) (uint64, error) { + ops := common.NewOptions(options) + utxos, err := b.backend.UTXOs(ops.Context(), chainID) + if err != nil { + return 0, err + } + + var ( + addrs = ops.Addresses(b.avaxAddrs) + minIssuanceTime = ops.MinIssuanceTime() + avaxAssetID = b.backend.AVAXAssetID() + balance uint64 + ) + for _, utxo := range utxos { + amount, _, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) + if !ok { + continue + } + + newBalance, err := math.Add64(balance, amount) + if err != nil { + return 0, err + } + balance = newBalance + } + + return balance, nil +} + +func (b *builder) NewImportTx( + chainID ids.ID, + to ethcommon.Address, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedImportTx, error) { + ops := common.NewOptions(options) + utxos, err := b.backend.UTXOs(ops.Context(), chainID) + if err != nil { + return nil, err + } + + var ( + addrs = ops.Addresses(b.avaxAddrs) + minIssuanceTime = ops.MinIssuanceTime() + avaxAssetID = b.backend.AVAXAssetID() + + importedInputs = make([]*avax.TransferableInput, 0, len(utxos)) + importedAmount uint64 + ) + for _, utxo := range utxos { + amount, inputSigIndices, ok := getSpendableAmount(utxo, addrs, minIssuanceTime, avaxAssetID) + if !ok { + continue + } + + importedInputs = append(importedInputs, &avax.TransferableInput{ + UTXOID: utxo.UTXOID, + Asset: utxo.Asset, + In: &secp256k1fx.TransferInput{ + Amt: amount, + Input: secp256k1fx.Input{ + SigIndices: inputSigIndices, + }, + }, + }) + + newImportedAmount, err := math.Add64(importedAmount, amount) + if err != nil { + return nil, err + } + importedAmount = newImportedAmount + } + + utils.Sort(importedInputs) + tx := &evm.UnsignedImportTx{ + NetworkID: b.backend.NetworkID(), + BlockchainID: b.backend.BlockchainID(), + SourceChain: chainID, + ImportedInputs: importedInputs, + } + + // We must initialize the bytes of the tx to calculate the initial cost + wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} + if err := wrappedTx.Sign(evm.Codec, nil); err != nil { + return nil, err + } + + gasUsedWithoutOutput, err := tx.GasUsed(true /*=IsApricotPhase5*/) + if err != nil { + return nil, err + } + gasUsedWithOutput := gasUsedWithoutOutput + evm.EVMOutputGas + + txFee, err := evm.CalculateDynamicFee(gasUsedWithOutput, baseFee) + if err != nil { + return nil, err + } + + if importedAmount <= txFee { + return nil, errInsufficientFunds + } + + tx.Outs = []evm.EVMOutput{{ + Address: to, + Amount: importedAmount - txFee, + AssetID: avaxAssetID, + }} + return tx, nil +} + +func (b *builder) NewExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedExportTx, error) { + var ( + avaxAssetID = b.backend.AVAXAssetID() + exportedOutputs = make([]*avax.TransferableOutput, len(outputs)) + exportedAmount uint64 + ) + for i, output := range outputs { + exportedOutputs[i] = &avax.TransferableOutput{ + Asset: avax.Asset{ID: avaxAssetID}, + Out: output, + } + + newExportedAmount, err := math.Add64(exportedAmount, output.Amt) + if err != nil { + return nil, err + } + exportedAmount = newExportedAmount + } + + avax.SortTransferableOutputs(exportedOutputs, evm.Codec) + tx := &evm.UnsignedExportTx{ + NetworkID: b.backend.NetworkID(), + BlockchainID: b.backend.BlockchainID(), + DestinationChain: chainID, + ExportedOutputs: exportedOutputs, + } + + // We must initialize the bytes of the tx to calculate the initial cost + wrappedTx := &evm.Tx{UnsignedAtomicTx: tx} + if err := wrappedTx.Sign(evm.Codec, nil); err != nil { + return nil, err + } + + cost, err := tx.GasUsed(true /*=IsApricotPhase5*/) + if err != nil { + return nil, err + } + + initialFee, err := evm.CalculateDynamicFee(cost, baseFee) + if err != nil { + return nil, err + } + + amountToConsume, err := math.Add64(exportedAmount, initialFee) + if err != nil { + return nil, err + } + + var ( + ops = common.NewOptions(options) + ctx = ops.Context() + addrs = ops.EthAddresses(b.ethAddrs) + inputs = make([]evm.EVMInput, 0, addrs.Len()) + ) + for addr := range addrs { + if amountToConsume == 0 { + break + } + + prevFee, err := evm.CalculateDynamicFee(cost, baseFee) + if err != nil { + return nil, err + } + + newCost := cost + evm.EVMInputGas + newFee, err := evm.CalculateDynamicFee(newCost, baseFee) + if err != nil { + return nil, err + } + + additionalFee := newFee - prevFee + + balance, err := b.backend.Balance(ctx, addr) + if err != nil { + return nil, err + } + + // Since the asset is AVAX, we divide by the avaxConversionRate to + // convert back to the correct denomination of AVAX that can be + // exported. + avaxBalance := new(big.Int).Div(balance, avaxConversionRate).Uint64() + + // If the balance for [addr] is insufficient to cover the additional + // cost of adding an input to the transaction, skip adding the input + // altogether. + if avaxBalance <= additionalFee { + continue + } + + // Update the cost for the next iteration + cost = newCost + + amountToConsume, err = math.Add64(amountToConsume, additionalFee) + if err != nil { + return nil, err + } + + nonce, err := b.backend.Nonce(ctx, addr) + if err != nil { + return nil, err + } + + inputAmount := math.Min(amountToConsume, avaxBalance) + inputs = append(inputs, evm.EVMInput{ + Address: addr, + Amount: inputAmount, + AssetID: avaxAssetID, + Nonce: nonce, + }) + amountToConsume -= inputAmount + } + + if amountToConsume > 0 { + return nil, errInsufficientFunds + } + + utils.Sort(inputs) + tx.Ins = inputs + return tx, nil +} + +func getSpendableAmount( + utxo *avax.UTXO, + addrs set.Set[ids.ShortID], + minIssuanceTime uint64, + avaxAssetID ids.ID, +) (uint64, []uint32, bool) { + if utxo.Asset.ID != avaxAssetID { + // Only AVAX can be imported + return 0, nil, false + } + + out, ok := utxo.Out.(*secp256k1fx.TransferOutput) + if !ok { + // Can't import an unknown transfer output type + return 0, nil, false + } + + inputSigIndices, ok := common.MatchOwners(&out.OutputOwners, addrs, minIssuanceTime) + return out.Amt, inputSigIndices, ok +} diff --git a/wallet/chain/c/builder_with_options.go b/wallet/chain/c/builder_with_options.go index 9b7ab8399484..8416dddf9928 100644 --- a/wallet/chain/c/builder_with_options.go +++ b/wallet/chain/c/builder_with_options.go @@ -3,81 +3,81 @@ package c -// import ( -// "math/big" +import ( + "math/big" -// "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/coreth/plugin/evm" -// ethcommon "github.com/ethereum/go-ethereum/common" + ethcommon "github.com/ethereum/go-ethereum/common" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) -// var _ Builder = (*builderWithOptions)(nil) +var _ Builder = (*builderWithOptions)(nil) -// type builderWithOptions struct { -// Builder -// options []common.Option -// } +type builderWithOptions struct { + Builder + options []common.Option +} -// // NewBuilderWithOptions returns a new transaction builder that will use the -// // given options by default. -// // -// // - [builder] is the builder that will be called to perform the underlying -// // operations. -// // - [options] will be provided to the builder in addition to the options -// // provided in the method calls. -// func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { -// return &builderWithOptions{ -// Builder: builder, -// options: options, -// } -// } +// NewBuilderWithOptions returns a new transaction builder that will use the +// given options by default. +// +// - [builder] is the builder that will be called to perform the underlying +// operations. +// - [options] will be provided to the builder in addition to the options +// provided in the method calls. +func NewBuilderWithOptions(builder Builder, options ...common.Option) Builder { + return &builderWithOptions{ + Builder: builder, + options: options, + } +} -// func (b *builderWithOptions) GetBalance( -// options ...common.Option, -// ) (*big.Int, error) { -// return b.Builder.GetBalance( -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) GetBalance( + options ...common.Option, +) (*big.Int, error) { + return b.Builder.GetBalance( + common.UnionOptions(b.options, options)..., + ) +} -// func (b *builderWithOptions) GetImportableBalance( -// chainID ids.ID, -// options ...common.Option, -// ) (uint64, error) { -// return b.Builder.GetImportableBalance( -// chainID, -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) GetImportableBalance( + chainID ids.ID, + options ...common.Option, +) (uint64, error) { + return b.Builder.GetImportableBalance( + chainID, + common.UnionOptions(b.options, options)..., + ) +} -// func (b *builderWithOptions) NewImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedImportTx, error) { -// return b.Builder.NewImportTx( -// chainID, -// to, -// baseFee, -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) NewImportTx( + chainID ids.ID, + to ethcommon.Address, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedImportTx, error) { + return b.Builder.NewImportTx( + chainID, + to, + baseFee, + common.UnionOptions(b.options, options)..., + ) +} -// func (b *builderWithOptions) NewExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// baseFee *big.Int, -// options ...common.Option, -// ) (*evm.UnsignedExportTx, error) { -// return b.Builder.NewExportTx( -// chainID, -// outputs, -// baseFee, -// common.UnionOptions(b.options, options)..., -// ) -// } +func (b *builderWithOptions) NewExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + baseFee *big.Int, + options ...common.Option, +) (*evm.UnsignedExportTx, error) { + return b.Builder.NewExportTx( + chainID, + outputs, + baseFee, + common.UnionOptions(b.options, options)..., + ) +} diff --git a/wallet/chain/c/context.go b/wallet/chain/c/context.go index 1c01d8fb55c8..d506b42f81fa 100644 --- a/wallet/chain/c/context.go +++ b/wallet/chain/c/context.go @@ -3,81 +3,81 @@ package c -// import ( -// stdcontext "context" +import ( + stdcontext "context" -// "github.com/ava-labs/avalanchego/api/info" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/avm" -// ) + "github.com/ava-labs/avalanchego/api/info" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/avm" +) -// var _ Context = (*context)(nil) +var _ Context = (*context)(nil) -// type Context interface { -// NetworkID() uint32 -// BlockchainID() ids.ID -// AVAXAssetID() ids.ID -// } +type Context interface { + NetworkID() uint32 + BlockchainID() ids.ID + AVAXAssetID() ids.ID +} -// type context struct { -// networkID uint32 -// blockchainID ids.ID -// avaxAssetID ids.ID -// } +type context struct { + networkID uint32 + blockchainID ids.ID + avaxAssetID ids.ID +} -// func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { -// infoClient := info.NewClient(uri) -// xChainClient := avm.NewClient(uri, "X") -// return NewContextFromClients(ctx, infoClient, xChainClient) -// } +func NewContextFromURI(ctx stdcontext.Context, uri string) (Context, error) { + infoClient := info.NewClient(uri) + xChainClient := avm.NewClient(uri, "X") + return NewContextFromClients(ctx, infoClient, xChainClient) +} -// func NewContextFromClients( -// ctx stdcontext.Context, -// infoClient info.Client, -// xChainClient avm.Client, -// ) (Context, error) { -// networkID, err := infoClient.GetNetworkID(ctx) -// if err != nil { -// return nil, err -// } +func NewContextFromClients( + ctx stdcontext.Context, + infoClient info.Client, + xChainClient avm.Client, +) (Context, error) { + networkID, err := infoClient.GetNetworkID(ctx) + if err != nil { + return nil, err + } -// chainID, err := infoClient.GetBlockchainID(ctx, "C") -// if err != nil { -// return nil, err -// } + chainID, err := infoClient.GetBlockchainID(ctx, "C") + if err != nil { + return nil, err + } -// asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") -// if err != nil { -// return nil, err -// } + asset, err := xChainClient.GetAssetDescription(ctx, "AVAX") + if err != nil { + return nil, err + } -// return NewContext( -// networkID, -// chainID, -// asset.AssetID, -// ), nil -// } + return NewContext( + networkID, + chainID, + asset.AssetID, + ), nil +} -// func NewContext( -// networkID uint32, -// blockchainID ids.ID, -// avaxAssetID ids.ID, -// ) Context { -// return &context{ -// networkID: networkID, -// blockchainID: blockchainID, -// avaxAssetID: avaxAssetID, -// } -// } +func NewContext( + networkID uint32, + blockchainID ids.ID, + avaxAssetID ids.ID, +) Context { + return &context{ + networkID: networkID, + blockchainID: blockchainID, + avaxAssetID: avaxAssetID, + } +} -// func (c *context) NetworkID() uint32 { -// return c.networkID -// } +func (c *context) NetworkID() uint32 { + return c.networkID +} -// func (c *context) BlockchainID() ids.ID { -// return c.blockchainID -// } +func (c *context) BlockchainID() ids.ID { + return c.blockchainID +} -// func (c *context) AVAXAssetID() ids.ID { -// return c.avaxAssetID -// } +func (c *context) AVAXAssetID() ids.ID { + return c.avaxAssetID +} diff --git a/wallet/chain/c/signer.go b/wallet/chain/c/signer.go index 4bedc378234b..4fd85ed3b532 100644 --- a/wallet/chain/c/signer.go +++ b/wallet/chain/c/signer.go @@ -3,221 +3,221 @@ package c -// import ( -// "errors" -// "fmt" - -// stdcontext "context" - -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/database" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils/crypto/keychain" -// "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" -// "github.com/ava-labs/avalanchego/utils/hashing" -// "github.com/ava-labs/avalanchego/utils/set" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/components/verify" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// ) - -// const version = 0 - -// var ( -// _ Signer = (*txSigner)(nil) - -// errUnknownInputType = errors.New("unknown input type") -// errUnknownCredentialType = errors.New("unknown credential type") -// errUnknownOutputType = errors.New("unknown output type") -// errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") - -// emptySig [secp256k1.SignatureLen]byte -// ) - -// type Signer interface { -// SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) -// SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error -// } - -// type EthKeychain interface { -// // The returned Signer can provide a signature for [addr] -// GetEth(addr ethcommon.Address) (keychain.Signer, bool) -// // Returns the set of addresses for which the accessor keeps an associated -// // signer -// EthAddresses() set.Set[ethcommon.Address] -// } - -// type SignerBackend interface { -// GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) -// } - -// type txSigner struct { -// avaxKC keychain.Keychain -// ethKC EthKeychain -// backend SignerBackend -// } - -// func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { -// return &txSigner{ -// avaxKC: avaxKC, -// ethKC: ethKC, -// backend: backend, -// } -// } - -// func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { -// tx := &evm.Tx{UnsignedAtomicTx: utx} -// return tx, s.SignAtomic(ctx, tx) -// } - -// func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { -// switch utx := tx.UnsignedAtomicTx.(type) { -// case *evm.UnsignedImportTx: -// signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) -// if err != nil { -// return err -// } -// return sign(tx, true, signers) -// case *evm.UnsignedExportTx: -// signers := s.getExportSigners(utx.Ins) -// return sign(tx, true, signers) -// default: -// return fmt.Errorf("%w: %T", errUnknownTxType, tx) -// } -// } - -// func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { -// txSigners := make([][]keychain.Signer, len(ins)) -// for credIndex, transferInput := range ins { -// input, ok := transferInput.In.(*secp256k1fx.TransferInput) -// if !ok { -// return nil, errUnknownInputType -// } - -// inputSigners := make([]keychain.Signer, len(input.SigIndices)) -// txSigners[credIndex] = inputSigners - -// utxoID := transferInput.InputID() -// utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) -// if err == database.ErrNotFound { -// // If we don't have access to the UTXO, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// if err != nil { -// return nil, err -// } - -// out, ok := utxo.Out.(*secp256k1fx.TransferOutput) -// if !ok { -// return nil, errUnknownOutputType -// } - -// for sigIndex, addrIndex := range input.SigIndices { -// if addrIndex >= uint32(len(out.Addrs)) { -// return nil, errInvalidUTXOSigIndex -// } - -// addr := out.Addrs[addrIndex] -// key, ok := s.avaxKC.Get(addr) -// if !ok { -// // If we don't have access to the key, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// inputSigners[sigIndex] = key -// } -// } -// return txSigners, nil -// } - -// func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { -// txSigners := make([][]keychain.Signer, len(ins)) -// for credIndex, input := range ins { -// inputSigners := make([]keychain.Signer, 1) -// txSigners[credIndex] = inputSigners - -// key, ok := s.ethKC.GetEth(input.Address) -// if !ok { -// // If we don't have access to the key, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// inputSigners[0] = key -// } -// return txSigners -// } - -// // TODO: remove [signHash] after the ledger supports signing all transactions. -// func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { -// unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) -// if err != nil { -// return fmt.Errorf("couldn't marshal unsigned tx: %w", err) -// } -// unsignedHash := hashing.ComputeHash256(unsignedBytes) - -// if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { -// tx.Creds = make([]verify.Verifiable, expectedLen) -// } - -// sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) -// for credIndex, inputSigners := range txSigners { -// credIntf := tx.Creds[credIndex] -// if credIntf == nil { -// credIntf = &secp256k1fx.Credential{} -// tx.Creds[credIndex] = credIntf -// } - -// cred, ok := credIntf.(*secp256k1fx.Credential) -// if !ok { -// return errUnknownCredentialType -// } -// if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { -// cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) -// } - -// for sigIndex, signer := range inputSigners { -// if signer == nil { -// // If we don't have access to the key, then we can't sign this -// // transaction. However, we can attempt to partially sign it. -// continue -// } -// addr := signer.Address() -// if sig := cred.Sigs[sigIndex]; sig != emptySig { -// // If this signature has already been populated, we can just -// // copy the needed signature for the future. -// sigCache[addr] = sig -// continue -// } - -// if sig, exists := sigCache[addr]; exists { -// // If this key has already produced a signature, we can just -// // copy the previous signature. -// cred.Sigs[sigIndex] = sig -// continue -// } - -// var sig []byte -// if signHash { -// sig, err = signer.SignHash(unsignedHash) -// } else { -// sig, err = signer.Sign(unsignedBytes) -// } -// if err != nil { -// return fmt.Errorf("problem signing tx: %w", err) -// } -// copy(cred.Sigs[sigIndex][:], sig) -// sigCache[addr] = cred.Sigs[sigIndex] -// } -// } - -// signedBytes, err := evm.Codec.Marshal(version, tx) -// if err != nil { -// return fmt.Errorf("couldn't marshal tx: %w", err) -// } -// tx.Initialize(unsignedBytes, signedBytes) -// return nil -// } +import ( + "errors" + "fmt" + + stdcontext "context" + + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/crypto/keychain" + "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" + "github.com/ava-labs/avalanchego/utils/hashing" + "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/components/verify" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" +) + +const version = 0 + +var ( + _ Signer = (*txSigner)(nil) + + errUnknownInputType = errors.New("unknown input type") + errUnknownCredentialType = errors.New("unknown credential type") + errUnknownOutputType = errors.New("unknown output type") + errInvalidUTXOSigIndex = errors.New("invalid UTXO signature index") + + emptySig [secp256k1.SignatureLen]byte +) + +type Signer interface { + SignUnsignedAtomic(ctx stdcontext.Context, tx evm.UnsignedAtomicTx) (*evm.Tx, error) + SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error +} + +type EthKeychain interface { + // The returned Signer can provide a signature for [addr] + GetEth(addr ethcommon.Address) (keychain.Signer, bool) + // Returns the set of addresses for which the accessor keeps an associated + // signer + EthAddresses() set.Set[ethcommon.Address] +} + +type SignerBackend interface { + GetUTXO(ctx stdcontext.Context, chainID, utxoID ids.ID) (*avax.UTXO, error) +} + +type txSigner struct { + avaxKC keychain.Keychain + ethKC EthKeychain + backend SignerBackend +} + +func NewSigner(avaxKC keychain.Keychain, ethKC EthKeychain, backend SignerBackend) Signer { + return &txSigner{ + avaxKC: avaxKC, + ethKC: ethKC, + backend: backend, + } +} + +func (s *txSigner) SignUnsignedAtomic(ctx stdcontext.Context, utx evm.UnsignedAtomicTx) (*evm.Tx, error) { + tx := &evm.Tx{UnsignedAtomicTx: utx} + return tx, s.SignAtomic(ctx, tx) +} + +func (s *txSigner) SignAtomic(ctx stdcontext.Context, tx *evm.Tx) error { + switch utx := tx.UnsignedAtomicTx.(type) { + case *evm.UnsignedImportTx: + signers, err := s.getImportSigners(ctx, utx.SourceChain, utx.ImportedInputs) + if err != nil { + return err + } + return sign(tx, true, signers) + case *evm.UnsignedExportTx: + signers := s.getExportSigners(utx.Ins) + return sign(tx, true, signers) + default: + return fmt.Errorf("%w: %T", errUnknownTxType, tx) + } +} + +func (s *txSigner) getImportSigners(ctx stdcontext.Context, sourceChainID ids.ID, ins []*avax.TransferableInput) ([][]keychain.Signer, error) { + txSigners := make([][]keychain.Signer, len(ins)) + for credIndex, transferInput := range ins { + input, ok := transferInput.In.(*secp256k1fx.TransferInput) + if !ok { + return nil, errUnknownInputType + } + + inputSigners := make([]keychain.Signer, len(input.SigIndices)) + txSigners[credIndex] = inputSigners + + utxoID := transferInput.InputID() + utxo, err := s.backend.GetUTXO(ctx, sourceChainID, utxoID) + if err == database.ErrNotFound { + // If we don't have access to the UTXO, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + if err != nil { + return nil, err + } + + out, ok := utxo.Out.(*secp256k1fx.TransferOutput) + if !ok { + return nil, errUnknownOutputType + } + + for sigIndex, addrIndex := range input.SigIndices { + if addrIndex >= uint32(len(out.Addrs)) { + return nil, errInvalidUTXOSigIndex + } + + addr := out.Addrs[addrIndex] + key, ok := s.avaxKC.Get(addr) + if !ok { + // If we don't have access to the key, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + inputSigners[sigIndex] = key + } + } + return txSigners, nil +} + +func (s *txSigner) getExportSigners(ins []evm.EVMInput) [][]keychain.Signer { + txSigners := make([][]keychain.Signer, len(ins)) + for credIndex, input := range ins { + inputSigners := make([]keychain.Signer, 1) + txSigners[credIndex] = inputSigners + + key, ok := s.ethKC.GetEth(input.Address) + if !ok { + // If we don't have access to the key, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + inputSigners[0] = key + } + return txSigners +} + +// TODO: remove [signHash] after the ledger supports signing all transactions. +func sign(tx *evm.Tx, signHash bool, txSigners [][]keychain.Signer) error { + unsignedBytes, err := evm.Codec.Marshal(version, &tx.UnsignedAtomicTx) + if err != nil { + return fmt.Errorf("couldn't marshal unsigned tx: %w", err) + } + unsignedHash := hashing.ComputeHash256(unsignedBytes) + + if expectedLen := len(txSigners); expectedLen != len(tx.Creds) { + tx.Creds = make([]verify.Verifiable, expectedLen) + } + + sigCache := make(map[ids.ShortID][secp256k1.SignatureLen]byte) + for credIndex, inputSigners := range txSigners { + credIntf := tx.Creds[credIndex] + if credIntf == nil { + credIntf = &secp256k1fx.Credential{} + tx.Creds[credIndex] = credIntf + } + + cred, ok := credIntf.(*secp256k1fx.Credential) + if !ok { + return errUnknownCredentialType + } + if expectedLen := len(inputSigners); expectedLen != len(cred.Sigs) { + cred.Sigs = make([][secp256k1.SignatureLen]byte, expectedLen) + } + + for sigIndex, signer := range inputSigners { + if signer == nil { + // If we don't have access to the key, then we can't sign this + // transaction. However, we can attempt to partially sign it. + continue + } + addr := signer.Address() + if sig := cred.Sigs[sigIndex]; sig != emptySig { + // If this signature has already been populated, we can just + // copy the needed signature for the future. + sigCache[addr] = sig + continue + } + + if sig, exists := sigCache[addr]; exists { + // If this key has already produced a signature, we can just + // copy the previous signature. + cred.Sigs[sigIndex] = sig + continue + } + + var sig []byte + if signHash { + sig, err = signer.SignHash(unsignedHash) + } else { + sig, err = signer.Sign(unsignedBytes) + } + if err != nil { + return fmt.Errorf("problem signing tx: %w", err) + } + copy(cred.Sigs[sigIndex][:], sig) + sigCache[addr] = cred.Sigs[sigIndex] + } + } + + signedBytes, err := evm.Codec.Marshal(version, tx) + if err != nil { + return fmt.Errorf("couldn't marshal tx: %w", err) + } + tx.Initialize(unsignedBytes, signedBytes) + return nil +} diff --git a/wallet/chain/c/wallet.go b/wallet/chain/c/wallet.go index ebee50a9a958..fb1a83d53dad 100644 --- a/wallet/chain/c/wallet.go +++ b/wallet/chain/c/wallet.go @@ -3,204 +3,204 @@ package c -// import ( -// "errors" -// "math/big" -// "time" - -// "github.com/ava-labs/coreth/ethclient" -// "github.com/ava-labs/coreth/plugin/evm" - -// ethcommon "github.com/ethereum/go-ethereum/common" - -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) - -// var ( -// _ Wallet = (*wallet)(nil) - -// errNotCommitted = errors.New("not committed") -// ) - -// type Wallet interface { -// Context - -// // Builder returns the builder that will be used to create the transactions. -// Builder() Builder - -// // Signer returns the signer that will be used to sign the transactions. -// Signer() Signer - -// // IssueImportTx creates, signs, and issues an import transaction that -// // attempts to consume all the available UTXOs and import the funds to [to]. -// // -// // - [chainID] specifies the chain to be importing funds from. -// // - [to] specifies where to send the imported funds to. -// IssueImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// options ...common.Option, -// ) (*evm.Tx, error) - -// // IssueExportTx creates, signs, and issues an export transaction that -// // attempts to send all the provided [outputs] to the requested [chainID]. -// // -// // - [chainID] specifies the chain to be exporting the funds to. -// // - [outputs] specifies the outputs to send to the [chainID]. -// IssueExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// options ...common.Option, -// ) (*evm.Tx, error) - -// // IssueUnsignedTx signs and issues the unsigned tx. -// IssueUnsignedAtomicTx( -// utx evm.UnsignedAtomicTx, -// options ...common.Option, -// ) (*evm.Tx, error) - -// // IssueAtomicTx issues the signed tx. -// IssueAtomicTx( -// tx *evm.Tx, -// options ...common.Option, -// ) error -// } - -// func NewWallet( -// builder Builder, -// signer Signer, -// avaxClient evm.Client, -// ethClient ethclient.Client, -// backend Backend, -// ) Wallet { -// return &wallet{ -// Backend: backend, -// builder: builder, -// signer: signer, -// avaxClient: avaxClient, -// ethClient: ethClient, -// } -// } - -// type wallet struct { -// Backend -// builder Builder -// signer Signer -// avaxClient evm.Client -// ethClient ethclient.Client -// } - -// func (w *wallet) Builder() Builder { -// return w.builder -// } - -// func (w *wallet) Signer() Signer { -// return w.signer -// } - -// func (w *wallet) IssueImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// options ...common.Option, -// ) (*evm.Tx, error) { -// baseFee, err := w.baseFee(options) -// if err != nil { -// return nil, err -// } - -// utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) -// if err != nil { -// return nil, err -// } -// return w.IssueUnsignedAtomicTx(utx, options...) -// } - -// func (w *wallet) IssueExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// options ...common.Option, -// ) (*evm.Tx, error) { -// baseFee, err := w.baseFee(options) -// if err != nil { -// return nil, err -// } - -// utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) -// if err != nil { -// return nil, err -// } -// return w.IssueUnsignedAtomicTx(utx, options...) -// } - -// func (w *wallet) IssueUnsignedAtomicTx( -// utx evm.UnsignedAtomicTx, -// options ...common.Option, -// ) (*evm.Tx, error) { -// ops := common.NewOptions(options) -// ctx := ops.Context() -// tx, err := w.signer.SignUnsignedAtomic(ctx, utx) -// if err != nil { -// return nil, err -// } - -// return tx, w.IssueAtomicTx(tx, options...) -// } - -// func (w *wallet) IssueAtomicTx( -// tx *evm.Tx, -// options ...common.Option, -// ) error { -// ops := common.NewOptions(options) -// ctx := ops.Context() -// txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) -// if err != nil { -// return err -// } - -// if f := ops.PostIssuanceFunc(); f != nil { -// f(txID) -// } - -// if ops.AssumeDecided() { -// return w.Backend.AcceptAtomicTx(ctx, tx) -// } - -// pollFrequency := ops.PollFrequency() -// ticker := time.NewTicker(pollFrequency) -// defer ticker.Stop() - -// for { -// status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) -// if err != nil { -// return err -// } - -// switch status { -// case evm.Accepted: -// return w.Backend.AcceptAtomicTx(ctx, tx) -// case evm.Dropped, evm.Unknown: -// return errNotCommitted -// } - -// // The tx is Processing. - -// select { -// case <-ticker.C: -// case <-ctx.Done(): -// return ctx.Err() -// } -// } -// } - -// func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { -// ops := common.NewOptions(options) -// baseFee := ops.BaseFee(nil) -// if baseFee != nil { -// return baseFee, nil -// } - -// ctx := ops.Context() -// return w.ethClient.EstimateBaseFee(ctx) -// } +import ( + "errors" + "math/big" + "time" + + "github.com/ava-labs/coreth/ethclient" + "github.com/ava-labs/coreth/plugin/evm" + + ethcommon "github.com/ethereum/go-ethereum/common" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) + +var ( + _ Wallet = (*wallet)(nil) + + errNotCommitted = errors.New("not committed") +) + +type Wallet interface { + Context + + // Builder returns the builder that will be used to create the transactions. + Builder() Builder + + // Signer returns the signer that will be used to sign the transactions. + Signer() Signer + + // IssueImportTx creates, signs, and issues an import transaction that + // attempts to consume all the available UTXOs and import the funds to [to]. + // + // - [chainID] specifies the chain to be importing funds from. + // - [to] specifies where to send the imported funds to. + IssueImportTx( + chainID ids.ID, + to ethcommon.Address, + options ...common.Option, + ) (*evm.Tx, error) + + // IssueExportTx creates, signs, and issues an export transaction that + // attempts to send all the provided [outputs] to the requested [chainID]. + // + // - [chainID] specifies the chain to be exporting the funds to. + // - [outputs] specifies the outputs to send to the [chainID]. + IssueExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + options ...common.Option, + ) (*evm.Tx, error) + + // IssueUnsignedTx signs and issues the unsigned tx. + IssueUnsignedAtomicTx( + utx evm.UnsignedAtomicTx, + options ...common.Option, + ) (*evm.Tx, error) + + // IssueAtomicTx issues the signed tx. + IssueAtomicTx( + tx *evm.Tx, + options ...common.Option, + ) error +} + +func NewWallet( + builder Builder, + signer Signer, + avaxClient evm.Client, + ethClient ethclient.Client, + backend Backend, +) Wallet { + return &wallet{ + Backend: backend, + builder: builder, + signer: signer, + avaxClient: avaxClient, + ethClient: ethClient, + } +} + +type wallet struct { + Backend + builder Builder + signer Signer + avaxClient evm.Client + ethClient ethclient.Client +} + +func (w *wallet) Builder() Builder { + return w.builder +} + +func (w *wallet) Signer() Signer { + return w.signer +} + +func (w *wallet) IssueImportTx( + chainID ids.ID, + to ethcommon.Address, + options ...common.Option, +) (*evm.Tx, error) { + baseFee, err := w.baseFee(options) + if err != nil { + return nil, err + } + + utx, err := w.builder.NewImportTx(chainID, to, baseFee, options...) + if err != nil { + return nil, err + } + return w.IssueUnsignedAtomicTx(utx, options...) +} + +func (w *wallet) IssueExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + options ...common.Option, +) (*evm.Tx, error) { + baseFee, err := w.baseFee(options) + if err != nil { + return nil, err + } + + utx, err := w.builder.NewExportTx(chainID, outputs, baseFee, options...) + if err != nil { + return nil, err + } + return w.IssueUnsignedAtomicTx(utx, options...) +} + +func (w *wallet) IssueUnsignedAtomicTx( + utx evm.UnsignedAtomicTx, + options ...common.Option, +) (*evm.Tx, error) { + ops := common.NewOptions(options) + ctx := ops.Context() + tx, err := w.signer.SignUnsignedAtomic(ctx, utx) + if err != nil { + return nil, err + } + + return tx, w.IssueAtomicTx(tx, options...) +} + +func (w *wallet) IssueAtomicTx( + tx *evm.Tx, + options ...common.Option, +) error { + ops := common.NewOptions(options) + ctx := ops.Context() + txID, err := w.avaxClient.IssueTx(ctx, tx.SignedBytes()) + if err != nil { + return err + } + + if f := ops.PostIssuanceFunc(); f != nil { + f(txID) + } + + if ops.AssumeDecided() { + return w.Backend.AcceptAtomicTx(ctx, tx) + } + + pollFrequency := ops.PollFrequency() + ticker := time.NewTicker(pollFrequency) + defer ticker.Stop() + + for { + status, err := w.avaxClient.GetAtomicTxStatus(ctx, txID) + if err != nil { + return err + } + + switch status { + case evm.Accepted: + return w.Backend.AcceptAtomicTx(ctx, tx) + case evm.Dropped, evm.Unknown: + return errNotCommitted + } + + // The tx is Processing. + + select { + case <-ticker.C: + case <-ctx.Done(): + return ctx.Err() + } + } +} + +func (w *wallet) baseFee(options []common.Option) (*big.Int, error) { + ops := common.NewOptions(options) + baseFee := ops.BaseFee(nil) + if baseFee != nil { + return baseFee, nil + } + + ctx := ops.Context() + return w.ethClient.EstimateBaseFee(ctx) +} diff --git a/wallet/chain/c/wallet_with_options.go b/wallet/chain/c/wallet_with_options.go index fd69a6d4fd02..7d6193683d49 100644 --- a/wallet/chain/c/wallet_with_options.go +++ b/wallet/chain/c/wallet_with_options.go @@ -3,80 +3,80 @@ package c -// import ( -// "github.com/ava-labs/coreth/plugin/evm" +import ( + "github.com/ava-labs/coreth/plugin/evm" -// ethcommon "github.com/ethereum/go-ethereum/common" + ethcommon "github.com/ethereum/go-ethereum/common" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" -// ) + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" +) -// var _ Wallet = (*walletWithOptions)(nil) +var _ Wallet = (*walletWithOptions)(nil) -// func NewWalletWithOptions( -// wallet Wallet, -// options ...common.Option, -// ) Wallet { -// return &walletWithOptions{ -// Wallet: wallet, -// options: options, -// } -// } +func NewWalletWithOptions( + wallet Wallet, + options ...common.Option, +) Wallet { + return &walletWithOptions{ + Wallet: wallet, + options: options, + } +} -// type walletWithOptions struct { -// Wallet -// options []common.Option -// } +type walletWithOptions struct { + Wallet + options []common.Option +} -// func (w *walletWithOptions) Builder() Builder { -// return NewBuilderWithOptions( -// w.Wallet.Builder(), -// w.options..., -// ) -// } +func (w *walletWithOptions) Builder() Builder { + return NewBuilderWithOptions( + w.Wallet.Builder(), + w.options..., + ) +} -// func (w *walletWithOptions) IssueImportTx( -// chainID ids.ID, -// to ethcommon.Address, -// options ...common.Option, -// ) (*evm.Tx, error) { -// return w.Wallet.IssueImportTx( -// chainID, -// to, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueImportTx( + chainID ids.ID, + to ethcommon.Address, + options ...common.Option, +) (*evm.Tx, error) { + return w.Wallet.IssueImportTx( + chainID, + to, + common.UnionOptions(w.options, options)..., + ) +} -// func (w *walletWithOptions) IssueExportTx( -// chainID ids.ID, -// outputs []*secp256k1fx.TransferOutput, -// options ...common.Option, -// ) (*evm.Tx, error) { -// return w.Wallet.IssueExportTx( -// chainID, -// outputs, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueExportTx( + chainID ids.ID, + outputs []*secp256k1fx.TransferOutput, + options ...common.Option, +) (*evm.Tx, error) { + return w.Wallet.IssueExportTx( + chainID, + outputs, + common.UnionOptions(w.options, options)..., + ) +} -// func (w *walletWithOptions) IssueUnsignedAtomicTx( -// utx evm.UnsignedAtomicTx, -// options ...common.Option, -// ) (*evm.Tx, error) { -// return w.Wallet.IssueUnsignedAtomicTx( -// utx, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueUnsignedAtomicTx( + utx evm.UnsignedAtomicTx, + options ...common.Option, +) (*evm.Tx, error) { + return w.Wallet.IssueUnsignedAtomicTx( + utx, + common.UnionOptions(w.options, options)..., + ) +} -// func (w *walletWithOptions) IssueAtomicTx( -// tx *evm.Tx, -// options ...common.Option, -// ) error { -// return w.Wallet.IssueAtomicTx( -// tx, -// common.UnionOptions(w.options, options)..., -// ) -// } +func (w *walletWithOptions) IssueAtomicTx( + tx *evm.Tx, + options ...common.Option, +) error { + return w.Wallet.IssueAtomicTx( + tx, + common.UnionOptions(w.options, options)..., + ) +} diff --git a/wallet/subnet/primary/api.go b/wallet/subnet/primary/api.go index 3260c05a0a1b..3ac72c217884 100644 --- a/wallet/subnet/primary/api.go +++ b/wallet/subnet/primary/api.go @@ -5,6 +5,12 @@ package primary import ( "context" + "fmt" + + "github.com/ava-labs/coreth/ethclient" + "github.com/ava-labs/coreth/plugin/evm" + + "github.com/ethereum/go-ethereum/common" "github.com/ava-labs/avalanchego/api/info" "github.com/ava-labs/avalanchego/codec" @@ -16,6 +22,7 @@ import ( "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/platformvm" "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" ) @@ -52,9 +59,9 @@ type AVAXState struct { PCTX p.Context XClient avm.Client XCTX x.Context - // CClient evm.Client - // CCTX c.Context - UTXOs UTXOs + CClient evm.Client + CCTX c.Context + UTXOs UTXOs } func FetchState( @@ -68,7 +75,7 @@ func FetchState( infoClient := info.NewClient(uri) pClient := platformvm.NewClient(uri) xClient := avm.NewClient(uri, "X") - // cClient := evm.NewCChainClient(uri) + cClient := evm.NewCChainClient(uri) pCTX, err := p.NewContextFromClients(ctx, infoClient, xClient) if err != nil { @@ -80,10 +87,10 @@ func FetchState( return nil, err } - // cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) - // if err != nil { - // return nil, err - // } + cCTX, err := c.NewContextFromClients(ctx, infoClient, xClient) + if err != nil { + return nil, err + } utxos := NewUTXOs() addrList := addrs.List() @@ -102,11 +109,11 @@ func FetchState( client: xClient, codec: x.Parser.Codec(), }, - // { - // id: cCTX.BlockchainID(), - // client: cClient, - // codec: evm.Codec, - // }, + { + id: cCTX.BlockchainID(), + client: cClient, + codec: evm.Codec, + }, } for _, destinationChain := range chains { for _, sourceChain := range chains { @@ -129,52 +136,52 @@ func FetchState( PCTX: pCTX, XClient: xClient, XCTX: xCTX, - // CClient: cClient, - // CCTX: cCTX, - UTXOs: utxos, + CClient: cClient, + CCTX: cCTX, + UTXOs: utxos, }, nil } -// type EthState struct { -// Client ethclient.Client -// Accounts map[common.Address]*c.Account -// } - -// func FetchEthState( -// ctx context.Context, -// uri string, -// addrs set.Set[common.Address], -// ) (*EthState, error) { -// path := fmt.Sprintf( -// "%s/ext/%s/C/rpc", -// uri, -// constants.ChainAliasPrefix, -// ) -// client, err := ethclient.Dial(path) -// if err != nil { -// return nil, err -// } - -// accounts := make(map[common.Address]*c.Account, addrs.Len()) -// for addr := range addrs { -// balance, err := client.BalanceAt(ctx, addr, nil) -// if err != nil { -// return nil, err -// } -// nonce, err := client.NonceAt(ctx, addr, nil) -// if err != nil { -// return nil, err -// } -// accounts[addr] = &c.Account{ -// Balance: balance, -// Nonce: nonce, -// } -// } -// return &EthState{ -// Client: client, -// Accounts: accounts, -// }, nil -// } +type EthState struct { + Client ethclient.Client + Accounts map[common.Address]*c.Account +} + +func FetchEthState( + ctx context.Context, + uri string, + addrs set.Set[common.Address], +) (*EthState, error) { + path := fmt.Sprintf( + "%s/ext/%s/C/rpc", + uri, + constants.ChainAliasPrefix, + ) + client, err := ethclient.Dial(path) + if err != nil { + return nil, err + } + + accounts := make(map[common.Address]*c.Account, addrs.Len()) + for addr := range addrs { + balance, err := client.BalanceAt(ctx, addr, nil) + if err != nil { + return nil, err + } + nonce, err := client.NonceAt(ctx, addr, nil) + if err != nil { + return nil, err + } + accounts[addr] = &c.Account{ + Balance: balance, + Nonce: nonce, + } + } + return &EthState{ + Client: client, + Accounts: accounts, + }, nil +} // AddAllUTXOs fetches all the UTXOs referenced by [addresses] that were sent // from [sourceChainID] to [destinationChainID] from the [client]. It then uses diff --git a/wallet/subnet/primary/example_test.go b/wallet/subnet/primary/example_test.go index 4a73e8c070b2..483c049d4ac0 100644 --- a/wallet/subnet/primary/example_test.go +++ b/wallet/subnet/primary/example_test.go @@ -30,7 +30,7 @@ func ExampleWallet() { wallet, err := MakeWallet(ctx, &WalletConfig{ URI: LocalAPIURI, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet with: %s\n", err) diff --git a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go index 21c081d2982b..d5e8ce422307 100644 --- a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/main.go @@ -46,9 +46,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/add-primary-validator/main.go b/wallet/subnet/primary/examples/add-primary-validator/main.go index 13c28f995f63..a56dae23db3a 100644 --- a/wallet/subnet/primary/examples/add-primary-validator/main.go +++ b/wallet/subnet/primary/examples/add-primary-validator/main.go @@ -45,7 +45,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/c-chain-export/main.go b/wallet/subnet/primary/examples/c-chain-export/main.go index a6b9a0c810b8..fec55c899feb 100644 --- a/wallet/subnet/primary/examples/c-chain-export/main.go +++ b/wallet/subnet/primary/examples/c-chain-export/main.go @@ -3,70 +3,70 @@ package main -// import ( -// "context" -// "log" -// "time" +import ( + "context" + "log" + "time" -// "github.com/ava-labs/avalanchego/genesis" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary" -// ) + "github.com/ava-labs/avalanchego/genesis" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary" +) -// func main() { -// key := genesis.EWOQKey -// uri := primary.LocalAPIURI -// kc := secp256k1fx.NewKeychain(key) -// avaxAddr := key.Address() +func main() { + key := genesis.EWOQKey + uri := primary.LocalAPIURI + kc := secp256k1fx.NewKeychain(key) + avaxAddr := key.Address() -// ctx := context.Background() + ctx := context.Background() -// // MakeWallet fetches the available UTXOs owned by [kc] on the network that -// // [uri] is hosting. -// walletSyncStartTime := time.Now() -// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ -// URI: uri, -// AVAXKeychain: kc, -// EthKeychain: kc, -// }) -// if err != nil { -// log.Fatalf("failed to initialize wallet: %s\n", err) -// } -// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) + // MakeWallet fetches the available UTXOs owned by [kc] on the network that + // [uri] is hosting. + walletSyncStartTime := time.Now() + wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, + }) + if err != nil { + log.Fatalf("failed to initialize wallet: %s\n", err) + } + log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) -// // Get the P-chain wallet -// pWallet := wallet.P() -// cWallet := wallet.C() + // Get the P-chain wallet + pWallet := wallet.P() + cWallet := wallet.C() -// // Pull out useful constants to use when issuing transactions. -// cChainID := cWallet.BlockchainID() -// owner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// avaxAddr, -// }, -// } + // Pull out useful constants to use when issuing transactions. + cChainID := cWallet.BlockchainID() + owner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + avaxAddr, + }, + } -// exportStartTime := time.Now() -// exportTx, err := cWallet.IssueExportTx( -// constants.PlatformChainID, -// []*secp256k1fx.TransferOutput{{ -// Amt: units.Avax, -// OutputOwners: owner, -// }}, -// ) -// if err != nil { -// log.Fatalf("failed to issue export transaction: %s\n", err) -// } -// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) + exportStartTime := time.Now() + exportTx, err := cWallet.IssueExportTx( + constants.PlatformChainID, + []*secp256k1fx.TransferOutput{{ + Amt: units.Avax, + OutputOwners: owner, + }}, + ) + if err != nil { + log.Fatalf("failed to issue export transaction: %s\n", err) + } + log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) -// importStartTime := time.Now() -// importTx, err := pWallet.IssueImportTx(cChainID, &owner) -// if err != nil { -// log.Fatalf("failed to issue import transaction: %s\n", err) -// } -// log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) -// } + importStartTime := time.Now() + importTx, err := pWallet.IssueImportTx(cChainID, &owner) + if err != nil { + log.Fatalf("failed to issue import transaction: %s\n", err) + } + log.Printf("issued import %s in %s\n", importTx.ID(), time.Since(importStartTime)) +} diff --git a/wallet/subnet/primary/examples/c-chain-import/main.go b/wallet/subnet/primary/examples/c-chain-import/main.go index 2d9b8a244cb0..b4dc4e603eb3 100644 --- a/wallet/subnet/primary/examples/c-chain-import/main.go +++ b/wallet/subnet/primary/examples/c-chain-import/main.go @@ -3,75 +3,75 @@ package main -// import ( -// "context" -// "log" -// "time" +import ( + "context" + "log" + "time" -// "github.com/ava-labs/coreth/plugin/evm" + "github.com/ava-labs/coreth/plugin/evm" -// "github.com/ava-labs/avalanchego/genesis" -// "github.com/ava-labs/avalanchego/ids" -// "github.com/ava-labs/avalanchego/utils/constants" -// "github.com/ava-labs/avalanchego/utils/units" -// "github.com/ava-labs/avalanchego/vms/components/avax" -// "github.com/ava-labs/avalanchego/vms/secp256k1fx" -// "github.com/ava-labs/avalanchego/wallet/subnet/primary" -// ) + "github.com/ava-labs/avalanchego/genesis" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/constants" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/vms/components/avax" + "github.com/ava-labs/avalanchego/vms/secp256k1fx" + "github.com/ava-labs/avalanchego/wallet/subnet/primary" +) -// func main() { -// key := genesis.EWOQKey -// uri := primary.LocalAPIURI -// kc := secp256k1fx.NewKeychain(key) -// avaxAddr := key.Address() -// ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) +func main() { + key := genesis.EWOQKey + uri := primary.LocalAPIURI + kc := secp256k1fx.NewKeychain(key) + avaxAddr := key.Address() + ethAddr := evm.PublicKeyToEthAddress(key.PublicKey()) -// ctx := context.Background() + ctx := context.Background() -// // MakeWallet fetches the available UTXOs owned by [kc] on the network that -// // [uri] is hosting. -// walletSyncStartTime := time.Now() -// wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ -// URI: uri, -// AVAXKeychain: kc, -// EthKeychain: kc, -// }) -// if err != nil { -// log.Fatalf("failed to initialize wallet: %s\n", err) -// } -// log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) + // MakeWallet fetches the available UTXOs owned by [kc] on the network that + // [uri] is hosting. + walletSyncStartTime := time.Now() + wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, + }) + if err != nil { + log.Fatalf("failed to initialize wallet: %s\n", err) + } + log.Printf("synced wallet in %s\n", time.Since(walletSyncStartTime)) -// // Get the P-chain wallet -// pWallet := wallet.P() -// cWallet := wallet.C() + // Get the P-chain wallet + pWallet := wallet.P() + cWallet := wallet.C() -// // Pull out useful constants to use when issuing transactions. -// cChainID := cWallet.BlockchainID() -// avaxAssetID := cWallet.AVAXAssetID() -// owner := secp256k1fx.OutputOwners{ -// Threshold: 1, -// Addrs: []ids.ShortID{ -// avaxAddr, -// }, -// } + // Pull out useful constants to use when issuing transactions. + cChainID := cWallet.BlockchainID() + avaxAssetID := cWallet.AVAXAssetID() + owner := secp256k1fx.OutputOwners{ + Threshold: 1, + Addrs: []ids.ShortID{ + avaxAddr, + }, + } -// exportStartTime := time.Now() -// exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ -// Asset: avax.Asset{ID: avaxAssetID}, -// Out: &secp256k1fx.TransferOutput{ -// Amt: units.Avax, -// OutputOwners: owner, -// }, -// }}) -// if err != nil { -// log.Fatalf("failed to issue export transaction: %s\n", err) -// } -// log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) + exportStartTime := time.Now() + exportTx, err := pWallet.IssueExportTx(cChainID, []*avax.TransferableOutput{{ + Asset: avax.Asset{ID: avaxAssetID}, + Out: &secp256k1fx.TransferOutput{ + Amt: units.Avax, + OutputOwners: owner, + }, + }}) + if err != nil { + log.Fatalf("failed to issue export transaction: %s\n", err) + } + log.Printf("issued export %s in %s\n", exportTx.ID(), time.Since(exportStartTime)) -// importStartTime := time.Now() -// importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) -// if err != nil { -// log.Fatalf("failed to issue import transaction: %s\n", err) -// } -// log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) -// } + importStartTime := time.Now() + importTx, err := cWallet.IssueImportTx(constants.PlatformChainID, ethAddr) + if err != nil { + log.Fatalf("failed to issue import transaction: %s\n", err) + } + log.Printf("issued import %s to %s in %s\n", importTx.ID(), ethAddr.Hex(), time.Since(importStartTime)) +} diff --git a/wallet/subnet/primary/examples/create-asset/main.go b/wallet/subnet/primary/examples/create-asset/main.go index 0bccfbb5fc52..30804f083df6 100644 --- a/wallet/subnet/primary/examples/create-asset/main.go +++ b/wallet/subnet/primary/examples/create-asset/main.go @@ -30,7 +30,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-chain/main.go b/wallet/subnet/primary/examples/create-chain/main.go index 521a3cca53cf..5e6898a1b649 100644 --- a/wallet/subnet/primary/examples/create-chain/main.go +++ b/wallet/subnet/primary/examples/create-chain/main.go @@ -41,9 +41,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/examples/create-locked-stakeable/main.go b/wallet/subnet/primary/examples/create-locked-stakeable/main.go index 92f1b5cb0e1b..e688968e9e8a 100644 --- a/wallet/subnet/primary/examples/create-locked-stakeable/main.go +++ b/wallet/subnet/primary/examples/create-locked-stakeable/main.go @@ -39,7 +39,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/create-subnet/main.go b/wallet/subnet/primary/examples/create-subnet/main.go index 3e8d69bc016a..add98ea7931c 100644 --- a/wallet/subnet/primary/examples/create-subnet/main.go +++ b/wallet/subnet/primary/examples/create-subnet/main.go @@ -28,7 +28,7 @@ func main() { wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ URI: uri, AVAXKeychain: kc, - // EthKeychain: kc, + EthKeychain: kc, }) if err != nil { log.Fatalf("failed to initialize wallet: %s\n", err) diff --git a/wallet/subnet/primary/examples/remove-subnet-validator/main.go b/wallet/subnet/primary/examples/remove-subnet-validator/main.go index 46f4b85124db..2842c7c0a790 100644 --- a/wallet/subnet/primary/examples/remove-subnet-validator/main.go +++ b/wallet/subnet/primary/examples/remove-subnet-validator/main.go @@ -38,9 +38,9 @@ func main() { // [uri] is hosting and registers [subnetID]. walletSyncStartTime := time.Now() wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{ - URI: uri, - AVAXKeychain: kc, - // EthKeychain: kc, + URI: uri, + AVAXKeychain: kc, + EthKeychain: kc, PChainTxsToFetch: set.Of(subnetID), }) if err != nil { diff --git a/wallet/subnet/primary/wallet.go b/wallet/subnet/primary/wallet.go index de50d12f866b..54de390d029c 100644 --- a/wallet/subnet/primary/wallet.go +++ b/wallet/subnet/primary/wallet.go @@ -11,6 +11,7 @@ import ( "github.com/ava-labs/avalanchego/utils/crypto/keychain" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/platformvm/txs" + "github.com/ava-labs/avalanchego/wallet/chain/c" "github.com/ava-labs/avalanchego/wallet/chain/p" "github.com/ava-labs/avalanchego/wallet/chain/x" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" @@ -22,13 +23,13 @@ var _ Wallet = (*wallet)(nil) type Wallet interface { P() p.Wallet X() x.Wallet - // C() c.Wallet + C() c.Wallet } type wallet struct { p p.Wallet x x.Wallet - // c c.Wallet + c c.Wallet } func (w *wallet) P() p.Wallet { @@ -39,16 +40,16 @@ func (w *wallet) X() x.Wallet { return w.x } -// func (w *wallet) C() c.Wallet { -// return w.c -// } +func (w *wallet) C() c.Wallet { + return w.c +} // Creates a new default wallet -func NewWallet(p p.Wallet, x x.Wallet /*, c c.Wallet*/) Wallet { +func NewWallet(p p.Wallet, x x.Wallet, c c.Wallet) Wallet { return &wallet{ p: p, x: x, - // c: c, + c: c, } } @@ -57,7 +58,7 @@ func NewWalletWithOptions(w Wallet, options ...common.Option) Wallet { return NewWallet( p.NewWalletWithOptions(w.P(), options...), x.NewWalletWithOptions(w.X(), options...), - // c.NewWalletWithOptions(w.C(), options...), + c.NewWalletWithOptions(w.C(), options...), ) } @@ -66,7 +67,7 @@ type WalletConfig struct { URI string // required // Keys to use for signing all transactions. AVAXKeychain keychain.Keychain // required - // EthKeychain c.EthKeychain // required + EthKeychain c.EthKeychain // required // Set of P-chain transactions that the wallet should know about to be able // to generate transactions. PChainTxs map[ids.ID]*txs.Tx // optional @@ -92,11 +93,11 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { return nil, err } - // ethAddrs := config.EthKeychain.EthAddresses() - // ethState, err := FetchEthState(ctx, config.URI, ethAddrs) - // if err != nil { - // return nil, err - // } + ethAddrs := config.EthKeychain.EthAddresses() + ethState, err := FetchEthState(ctx, config.URI, ethAddrs) + if err != nil { + return nil, err + } pChainTxs := config.PChainTxs if pChainTxs == nil { @@ -126,15 +127,15 @@ func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) { xBuilder := x.NewBuilder(avaxAddrs, xBackend) xSigner := x.NewSigner(config.AVAXKeychain, xBackend) - // cChainID := avaxState.CCTX.BlockchainID() - // cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) - // cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) - // cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) - // cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) + cChainID := avaxState.CCTX.BlockchainID() + cUTXOs := NewChainUTXOs(cChainID, avaxState.UTXOs) + cBackend := c.NewBackend(avaxState.CCTX, cUTXOs, ethState.Accounts) + cBuilder := c.NewBuilder(avaxAddrs, ethAddrs, cBackend) + cSigner := c.NewSigner(config.AVAXKeychain, config.EthKeychain, cBackend) return NewWallet( p.NewWallet(pBuilder, pSigner, avaxState.PClient, pBackend), x.NewWallet(xBuilder, xSigner, avaxState.XClient, xBackend), - // c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), + c.NewWallet(cBuilder, cSigner, avaxState.CClient, ethState.Client, cBackend), ), nil } From b59fe3f215eb2f82077debbd3ccbbcba5b6a03fc Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 29 Nov 2023 10:17:27 +0100 Subject: [PATCH 35/36] fixed mere --- .../snowman/syncer/blocks_backfiller.go | 31 ++++++++++++++----- snow/engine/snowman/transitive.go | 2 +- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/snow/engine/snowman/syncer/blocks_backfiller.go b/snow/engine/snowman/syncer/blocks_backfiller.go index 9913ae5cda4e..cfbb093a8c45 100644 --- a/snow/engine/snowman/syncer/blocks_backfiller.go +++ b/snow/engine/snowman/syncer/blocks_backfiller.go @@ -16,6 +16,7 @@ import ( "github.com/ava-labs/avalanchego/snow/engine/common/tracker" "github.com/ava-labs/avalanchego/snow/engine/snowman/block" "github.com/ava-labs/avalanchego/snow/validators" + "github.com/ava-labs/avalanchego/utils/bimap" "github.com/ava-labs/avalanchego/utils/set" ) @@ -43,17 +44,18 @@ type BlockBackfillerConfig struct { type BlockBackfiller struct { BlockBackfillerConfig - fetchFrom set.Set[ids.NodeID] // picked from bootstrapper - outstandingRequests common.Requests // tracks which validators were asked for which block in which requests - interrupted bool // flag to allow backfilling restart after recovering from validators disconnections + fetchFrom set.Set[ids.NodeID] // picked from bootstrapper + outstandingRequests *bimap.BiMap[common.Request, ids.ID] // tracks which validators were asked for which block in which requests + interrupted bool // flag to allow backfilling restart after recovering from validators disconnections } func NewBlockBackfiller(cfg BlockBackfillerConfig) *BlockBackfiller { return &BlockBackfiller{ BlockBackfillerConfig: cfg, - fetchFrom: set.Of[ids.NodeID](cfg.Validators.GetValidatorIDs(cfg.Ctx.SubnetID)...), - interrupted: len(cfg.Peers.PreferredPeers()) > 0, + fetchFrom: set.Of[ids.NodeID](cfg.Validators.GetValidatorIDs(cfg.Ctx.SubnetID)...), + outstandingRequests: bimap.New[common.Request, ids.ID](), + interrupted: len(cfg.Peers.PreferredPeers()) > 0, } } @@ -80,7 +82,10 @@ func (bb *BlockBackfiller) Start(ctx context.Context) error { // response to a GetAncestors message to [nodeID] with request ID [requestID] func (bb *BlockBackfiller) Ancestors(ctx context.Context, nodeID ids.NodeID, requestID uint32, blks [][]byte) error { // Make sure this is in response to a request we made - wantedBlkID, ok := bb.outstandingRequests.Remove(nodeID, requestID) + wantedBlkID, ok := bb.outstandingRequests.DeleteKey(common.Request{ + NodeID: nodeID, + RequestID: requestID, + }) if !ok { // this message isn't in response to a request we made bb.Ctx.Log.Debug("received unexpected Ancestors", zap.Stringer("nodeID", nodeID), @@ -144,7 +149,10 @@ func (bb *BlockBackfiller) Ancestors(ctx context.Context, nodeID ids.NodeID, req } func (bb *BlockBackfiller) GetAncestorsFailed(ctx context.Context, nodeID ids.NodeID, requestID uint32) error { - blkID, ok := bb.outstandingRequests.Remove(nodeID, requestID) + blkID, ok := bb.outstandingRequests.DeleteKey(common.Request{ + NodeID: nodeID, + RequestID: requestID, + }) if !ok { bb.Ctx.Log.Debug("unexpectedly called GetAncestorsFailed", zap.Stringer("nodeID", nodeID), @@ -170,7 +178,14 @@ func (bb *BlockBackfiller) fetch(ctx context.Context, blkID ids.ID) error { // We only allow one outbound request at a time from a node bb.markUnavailable(validatorID) *bb.SharedRequestID++ - bb.outstandingRequests.Add(validatorID, *bb.SharedRequestID, blkID) + bb.outstandingRequests.Put( + common.Request{ + NodeID: validatorID, + RequestID: *bb.SharedRequestID, + }, + blkID, + ) + bb.Sender.SendGetAncestors(ctx, validatorID, *bb.SharedRequestID, blkID) return nil } diff --git a/snow/engine/snowman/transitive.go b/snow/engine/snowman/transitive.go index 3022191fc69f..258cb545595e 100644 --- a/snow/engine/snowman/transitive.go +++ b/snow/engine/snowman/transitive.go @@ -155,7 +155,7 @@ func newTransitive(config Config) (*Transitive, error) { Peers: config.Peers, AncestorsMaxContainersSent: config.AncestorsMaxContainersSent, AncestorsMaxContainersReceived: config.AncestorsMaxContainersReceived, - SharedRequestID: &t.RequestID, + SharedRequestID: &t.requestID, }, ) From 4ae3a08bb35bd999b85791bd70ceb82a6e700869 Mon Sep 17 00:00:00 2001 From: Alberto Benegiamo Date: Wed, 27 Dec 2023 17:15:51 +0100 Subject: [PATCH 36/36] fixed merge --- snow/engine/snowman/transitive_block_backfilling_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snow/engine/snowman/transitive_block_backfilling_test.go b/snow/engine/snowman/transitive_block_backfilling_test.go index c460712294cb..e4cd3bbea50a 100644 --- a/snow/engine/snowman/transitive_block_backfilling_test.go +++ b/snow/engine/snowman/transitive_block_backfilling_test.go @@ -486,7 +486,7 @@ type fullVM struct { } func setupBlockBackfillingTests(t *testing.T) (Config, *fullVM, *common.SenderTest, error) { - engCfg := DefaultConfig() + engCfg := DefaultConfig(t) var ( vm = &fullVM{