Commit d9613eb5 authored by linj's avatar linj Committed by vipwzw

update chain33 20190311

parent d5ec5da8
...@@ -472,3 +472,40 @@ func (acc *DB) mintReceipt(kv []*types.KeyValue, receipt proto.Message) *types.R ...@@ -472,3 +472,40 @@ func (acc *DB) mintReceipt(kv []*types.KeyValue, receipt proto.Message) *types.R
Logs: []*types.ReceiptLog{log1}, Logs: []*types.ReceiptLog{log1},
} }
} }
// Burn 然收
func (acc *DB) Burn(addr string, amount int64) (*types.Receipt, error) {
if !types.CheckAmount(amount) {
return nil, types.ErrAmount
}
accTo := acc.LoadAccount(addr)
if accTo.Balance < amount {
return nil, types.ErrNoBalance
}
copyAcc := *accTo
accTo.Balance = accTo.Balance - amount
receipt := &types.ReceiptAccountBurn{
Prev: &copyAcc,
Current: accTo,
}
kv := acc.GetKVSet(accTo)
acc.SaveKVSet(kv)
return acc.burnReceipt(kv, receipt), nil
}
func (acc *DB) burnReceipt(kv []*types.KeyValue, receipt proto.Message) *types.Receipt {
ty := int32(types.TyLogBurn)
log1 := &types.ReceiptLog{
Ty: ty,
Log: types.Encode(receipt),
}
return &types.Receipt{
Ty: types.ExecOk,
KV: kv,
Logs: []*types.ReceiptLog{log1},
}
}
...@@ -591,3 +591,13 @@ func TestDB_Mint(t *testing.T) { ...@@ -591,3 +591,13 @@ func TestDB_Mint(t *testing.T) {
t.Logf("Token mint addr balance [%d]", tokenCoin.LoadAccount(addr1).Balance) t.Logf("Token mint addr balance [%d]", tokenCoin.LoadAccount(addr1).Balance)
require.Equal(t, int64(1000*1e8+10*1e8), tokenCoin.LoadAccount(addr1).Balance) require.Equal(t, int64(1000*1e8+10*1e8), tokenCoin.LoadAccount(addr1).Balance)
} }
func TestDB_Burn(t *testing.T) {
_, tokenCoin := GenerAccDb()
tokenCoin.GenerAccData()
_, err := tokenCoin.Burn(addr1, 10*1e8)
require.NoError(t, err)
t.Logf("Token mint addr balance [%d]", tokenCoin.LoadAccount(addr1).Balance)
require.Equal(t, int64(1000*1e8-10*1e8), tokenCoin.LoadAccount(addr1).Balance)
}
...@@ -248,6 +248,53 @@ func (m *ReceiptAccountMint) GetCurrent() *Account { ...@@ -248,6 +248,53 @@ func (m *ReceiptAccountMint) GetCurrent() *Account {
return nil return nil
} }
type ReceiptAccountBurn struct {
Prev *Account `protobuf:"bytes,1,opt,name=prev,proto3" json:"prev,omitempty"`
Current *Account `protobuf:"bytes,2,opt,name=current,proto3" json:"current,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ReceiptAccountBurn) Reset() { *m = ReceiptAccountBurn{} }
func (m *ReceiptAccountBurn) String() string { return proto.CompactTextString(m) }
func (*ReceiptAccountBurn) ProtoMessage() {}
func (*ReceiptAccountBurn) Descriptor() ([]byte, []int) {
return fileDescriptor_8e28828dcb8d24f0, []int{4}
}
func (m *ReceiptAccountBurn) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptAccountBurn.Unmarshal(m, b)
}
func (m *ReceiptAccountBurn) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ReceiptAccountBurn.Marshal(b, m, deterministic)
}
func (m *ReceiptAccountBurn) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReceiptAccountBurn.Merge(m, src)
}
func (m *ReceiptAccountBurn) XXX_Size() int {
return xxx_messageInfo_ReceiptAccountBurn.Size(m)
}
func (m *ReceiptAccountBurn) XXX_DiscardUnknown() {
xxx_messageInfo_ReceiptAccountBurn.DiscardUnknown(m)
}
var xxx_messageInfo_ReceiptAccountBurn proto.InternalMessageInfo
func (m *ReceiptAccountBurn) GetPrev() *Account {
if m != nil {
return m.Prev
}
return nil
}
func (m *ReceiptAccountBurn) GetCurrent() *Account {
if m != nil {
return m.Current
}
return nil
}
//查询一个地址列表在某个执行器中余额 //查询一个地址列表在某个执行器中余额
type ReqBalance struct { type ReqBalance struct {
//地址列表 //地址列表
...@@ -266,7 +313,7 @@ func (m *ReqBalance) Reset() { *m = ReqBalance{} } ...@@ -266,7 +313,7 @@ func (m *ReqBalance) Reset() { *m = ReqBalance{} }
func (m *ReqBalance) String() string { return proto.CompactTextString(m) } func (m *ReqBalance) String() string { return proto.CompactTextString(m) }
func (*ReqBalance) ProtoMessage() {} func (*ReqBalance) ProtoMessage() {}
func (*ReqBalance) Descriptor() ([]byte, []int) { func (*ReqBalance) Descriptor() ([]byte, []int) {
return fileDescriptor_8e28828dcb8d24f0, []int{4} return fileDescriptor_8e28828dcb8d24f0, []int{5}
} }
func (m *ReqBalance) XXX_Unmarshal(b []byte) error { func (m *ReqBalance) XXX_Unmarshal(b []byte) error {
...@@ -334,7 +381,7 @@ func (m *Accounts) Reset() { *m = Accounts{} } ...@@ -334,7 +381,7 @@ func (m *Accounts) Reset() { *m = Accounts{} }
func (m *Accounts) String() string { return proto.CompactTextString(m) } func (m *Accounts) String() string { return proto.CompactTextString(m) }
func (*Accounts) ProtoMessage() {} func (*Accounts) ProtoMessage() {}
func (*Accounts) Descriptor() ([]byte, []int) { func (*Accounts) Descriptor() ([]byte, []int) {
return fileDescriptor_8e28828dcb8d24f0, []int{5} return fileDescriptor_8e28828dcb8d24f0, []int{6}
} }
func (m *Accounts) XXX_Unmarshal(b []byte) error { func (m *Accounts) XXX_Unmarshal(b []byte) error {
...@@ -374,7 +421,7 @@ func (m *ExecAccount) Reset() { *m = ExecAccount{} } ...@@ -374,7 +421,7 @@ func (m *ExecAccount) Reset() { *m = ExecAccount{} }
func (m *ExecAccount) String() string { return proto.CompactTextString(m) } func (m *ExecAccount) String() string { return proto.CompactTextString(m) }
func (*ExecAccount) ProtoMessage() {} func (*ExecAccount) ProtoMessage() {}
func (*ExecAccount) Descriptor() ([]byte, []int) { func (*ExecAccount) Descriptor() ([]byte, []int) {
return fileDescriptor_8e28828dcb8d24f0, []int{6} return fileDescriptor_8e28828dcb8d24f0, []int{7}
} }
func (m *ExecAccount) XXX_Unmarshal(b []byte) error { func (m *ExecAccount) XXX_Unmarshal(b []byte) error {
...@@ -421,7 +468,7 @@ func (m *AllExecBalance) Reset() { *m = AllExecBalance{} } ...@@ -421,7 +468,7 @@ func (m *AllExecBalance) Reset() { *m = AllExecBalance{} }
func (m *AllExecBalance) String() string { return proto.CompactTextString(m) } func (m *AllExecBalance) String() string { return proto.CompactTextString(m) }
func (*AllExecBalance) ProtoMessage() {} func (*AllExecBalance) ProtoMessage() {}
func (*AllExecBalance) Descriptor() ([]byte, []int) { func (*AllExecBalance) Descriptor() ([]byte, []int) {
return fileDescriptor_8e28828dcb8d24f0, []int{7} return fileDescriptor_8e28828dcb8d24f0, []int{8}
} }
func (m *AllExecBalance) XXX_Unmarshal(b []byte) error { func (m *AllExecBalance) XXX_Unmarshal(b []byte) error {
...@@ -473,7 +520,7 @@ func (m *ReqAllExecBalance) Reset() { *m = ReqAllExecBalance{} } ...@@ -473,7 +520,7 @@ func (m *ReqAllExecBalance) Reset() { *m = ReqAllExecBalance{} }
func (m *ReqAllExecBalance) String() string { return proto.CompactTextString(m) } func (m *ReqAllExecBalance) String() string { return proto.CompactTextString(m) }
func (*ReqAllExecBalance) ProtoMessage() {} func (*ReqAllExecBalance) ProtoMessage() {}
func (*ReqAllExecBalance) Descriptor() ([]byte, []int) { func (*ReqAllExecBalance) Descriptor() ([]byte, []int) {
return fileDescriptor_8e28828dcb8d24f0, []int{8} return fileDescriptor_8e28828dcb8d24f0, []int{9}
} }
func (m *ReqAllExecBalance) XXX_Unmarshal(b []byte) error { func (m *ReqAllExecBalance) XXX_Unmarshal(b []byte) error {
...@@ -534,6 +581,7 @@ func init() { ...@@ -534,6 +581,7 @@ func init() {
proto.RegisterType((*ReceiptExecAccountTransfer)(nil), "types.ReceiptExecAccountTransfer") proto.RegisterType((*ReceiptExecAccountTransfer)(nil), "types.ReceiptExecAccountTransfer")
proto.RegisterType((*ReceiptAccountTransfer)(nil), "types.ReceiptAccountTransfer") proto.RegisterType((*ReceiptAccountTransfer)(nil), "types.ReceiptAccountTransfer")
proto.RegisterType((*ReceiptAccountMint)(nil), "types.ReceiptAccountMint") proto.RegisterType((*ReceiptAccountMint)(nil), "types.ReceiptAccountMint")
proto.RegisterType((*ReceiptAccountBurn)(nil), "types.ReceiptAccountBurn")
proto.RegisterType((*ReqBalance)(nil), "types.ReqBalance") proto.RegisterType((*ReqBalance)(nil), "types.ReqBalance")
proto.RegisterType((*Accounts)(nil), "types.Accounts") proto.RegisterType((*Accounts)(nil), "types.Accounts")
proto.RegisterType((*ExecAccount)(nil), "types.ExecAccount") proto.RegisterType((*ExecAccount)(nil), "types.ExecAccount")
...@@ -544,32 +592,33 @@ func init() { ...@@ -544,32 +592,33 @@ func init() {
func init() { proto.RegisterFile("account.proto", fileDescriptor_8e28828dcb8d24f0) } func init() { proto.RegisterFile("account.proto", fileDescriptor_8e28828dcb8d24f0) }
var fileDescriptor_8e28828dcb8d24f0 = []byte{ var fileDescriptor_8e28828dcb8d24f0 = []byte{
// 427 bytes of a gzipped FileDescriptorProto // 434 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x54, 0xcd, 0x6a, 0x14, 0x41, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x54, 0xcd, 0x6e, 0x13, 0x31,
0x10, 0xa6, 0xf7, 0x27, 0x9b, 0xa9, 0xd5, 0x80, 0x7d, 0x08, 0x4d, 0x30, 0x38, 0xf6, 0x69, 0x0e, 0x10, 0x96, 0xf3, 0xd3, 0x74, 0x27, 0x50, 0x09, 0x1f, 0x2a, 0xab, 0xa2, 0x62, 0xf1, 0x69, 0x0f,
0xb2, 0x0b, 0x8e, 0x2f, 0x90, 0x80, 0xe0, 0x45, 0x84, 0xd6, 0x53, 0x2e, 0xd2, 0xd3, 0xa9, 0x75, 0x28, 0x91, 0x58, 0x5e, 0xa0, 0x91, 0x90, 0xb8, 0x20, 0x24, 0xc3, 0xa9, 0x17, 0xe4, 0x75, 0x27,
0x07, 0x27, 0x3d, 0x93, 0xee, 0x5e, 0x71, 0x7d, 0x00, 0x5f, 0x43, 0xf0, 0x49, 0xa5, 0x6b, 0x7b, 0x24, 0x22, 0xf5, 0x6e, 0x6d, 0x2f, 0x22, 0x3c, 0x00, 0xaf, 0x81, 0xc4, 0x93, 0x22, 0x4f, 0xbc,
0xb2, 0xb3, 0x06, 0x25, 0x07, 0xc1, 0xdb, 0xd4, 0xf7, 0x55, 0xd5, 0xf7, 0x75, 0x55, 0x31, 0xf0, 0xcd, 0x86, 0x0a, 0xd4, 0x03, 0xa8, 0xb7, 0x9d, 0xef, 0x1b, 0xcf, 0xf7, 0xd9, 0x33, 0xb3, 0xf0,
0x58, 0x1b, 0xd3, 0x6e, 0x6c, 0x58, 0x74, 0xae, 0x0d, 0x2d, 0x9f, 0x86, 0x6d, 0x87, 0x5e, 0x7e, 0x58, 0x1b, 0x53, 0xb7, 0x36, 0xcc, 0x1a, 0x57, 0x87, 0x9a, 0x8f, 0xc3, 0xb6, 0x41, 0x2f, 0x3f,
0x86, 0xd9, 0xc5, 0x0e, 0xe7, 0x67, 0x70, 0x6c, 0x36, 0xce, 0xa1, 0x35, 0x5b, 0xc1, 0x72, 0x56, 0xc3, 0xe4, 0x62, 0x87, 0xf3, 0x33, 0x38, 0x36, 0xad, 0x73, 0x68, 0xcd, 0x56, 0xb0, 0x9c, 0x15,
0x4c, 0xd5, 0x5d, 0xcc, 0x05, 0xcc, 0x2a, 0xdd, 0x68, 0x6b, 0x50, 0x8c, 0x72, 0x56, 0x8c, 0x55, 0x63, 0x75, 0x1b, 0x73, 0x01, 0x93, 0x4a, 0x6f, 0xb4, 0x35, 0x28, 0x06, 0x39, 0x2b, 0x86, 0xaa,
0x1f, 0xf2, 0x53, 0x38, 0x5a, 0xb9, 0xf6, 0x1b, 0x5a, 0x31, 0x26, 0x22, 0x45, 0x9c, 0xc3, 0x44, 0x0b, 0xf9, 0x29, 0x1c, 0x2d, 0x5d, 0xfd, 0x0d, 0xad, 0x18, 0x12, 0x91, 0x22, 0xce, 0x61, 0xa4,
0x5f, 0x5f, 0x3b, 0x31, 0xc9, 0x59, 0x91, 0x29, 0xfa, 0x96, 0xdf, 0x19, 0x9c, 0x29, 0x34, 0x58, 0xaf, 0xae, 0x9c, 0x18, 0xe5, 0xac, 0xc8, 0x14, 0x7d, 0xcb, 0xef, 0x0c, 0xce, 0x14, 0x1a, 0x5c,
0x77, 0xe1, 0xf5, 0x57, 0x34, 0x49, 0xf8, 0x83, 0xd3, 0xd6, 0xaf, 0xd0, 0x45, 0x03, 0x18, 0xe1, 0x37, 0xe1, 0xf5, 0x57, 0x34, 0x49, 0xf8, 0x83, 0xd3, 0xd6, 0x2f, 0xd1, 0x45, 0x03, 0x18, 0xe1,
0x58, 0xc6, 0xa8, 0xec, 0x2e, 0xe6, 0x12, 0x26, 0x9d, 0xc3, 0x2f, 0xa4, 0x3e, 0x7f, 0x79, 0xb2, 0x78, 0x8c, 0xd1, 0xb1, 0xdb, 0x98, 0x4b, 0x18, 0x35, 0x0e, 0xbf, 0x90, 0xfa, 0xf4, 0xe5, 0xc9,
0x20, 0xf7, 0x8b, 0xd4, 0x41, 0x11, 0xc7, 0x0b, 0x98, 0xed, 0x0c, 0x07, 0xf2, 0x72, 0x3f, 0xad, 0x8c, 0xdc, 0xcf, 0x52, 0x05, 0x45, 0x1c, 0x2f, 0x60, 0xb2, 0x33, 0x1c, 0xc8, 0xcb, 0xdd, 0xb4,
0xa7, 0xe5, 0x0a, 0x4e, 0x93, 0x8f, 0xdf, 0x3d, 0xf4, 0x3a, 0xec, 0x61, 0x3a, 0xa3, 0xbf, 0xeb, 0x8e, 0x96, 0x4b, 0x38, 0x4d, 0x3e, 0x7e, 0xf7, 0xd0, 0xe9, 0xb0, 0xfb, 0xe9, 0x0c, 0xfe, 0xae,
0x54, 0xc0, 0x0f, 0x75, 0xde, 0xd6, 0x36, 0xfc, 0x63, 0x8d, 0x9f, 0x0c, 0x40, 0xe1, 0xed, 0x65, 0x53, 0x01, 0x3f, 0xd4, 0x79, 0xbb, 0xb6, 0xe1, 0x7f, 0x6b, 0x2c, 0x5a, 0x67, 0xff, 0xb1, 0xc6,
0xda, 0xc7, 0x53, 0xc8, 0xe2, 0xac, 0xd1, 0x7b, 0xf4, 0x82, 0xe5, 0xe3, 0x22, 0x53, 0x7b, 0x20, 0x4f, 0x06, 0xa0, 0xf0, 0x66, 0x91, 0x7a, 0xfe, 0x14, 0xb2, 0xd8, 0x4f, 0xf4, 0x1e, 0xbd, 0x60,
0x6e, 0x2b, 0x8e, 0x14, 0x1d, 0x75, 0xcd, 0x54, 0x8a, 0x62, 0x95, 0x0f, 0x3a, 0xe0, 0x1b, 0xed, 0xf9, 0xb0, 0xc8, 0xd4, 0x1e, 0x88, 0x13, 0x11, 0xdb, 0x86, 0x8e, 0xaa, 0x66, 0x2a, 0x45, 0xf1,
0xd7, 0x34, 0xbc, 0x4c, 0xed, 0x01, 0x7e, 0x0e, 0xa0, 0xbd, 0xc7, 0xf0, 0x31, 0x66, 0xa7, 0x8d, 0x94, 0x0f, 0x3a, 0xe0, 0x1b, 0xed, 0x57, 0xd4, 0xa0, 0x4c, 0xed, 0x01, 0x7e, 0x0e, 0xa0, 0xbd,
0x66, 0x84, 0xc4, 0x35, 0xf2, 0xe7, 0xf0, 0x68, 0x47, 0xfb, 0xed, 0x4d, 0xd5, 0x36, 0x62, 0x4a, 0xc7, 0xf0, 0x31, 0x66, 0xa7, 0xa9, 0xc9, 0x08, 0x89, 0xa3, 0xc2, 0x9f, 0xc3, 0xa3, 0x1d, 0xed,
0x09, 0x73, 0xc2, 0xde, 0x13, 0x24, 0x5f, 0xc0, 0x71, 0x32, 0xee, 0x79, 0x0e, 0x63, 0x6d, 0x0c, 0xb7, 0xd7, 0x55, 0xbd, 0x11, 0x63, 0x4a, 0x98, 0x12, 0xf6, 0x9e, 0x20, 0xf9, 0x02, 0x8e, 0x93,
0x79, 0xbb, 0xff, 0xac, 0x48, 0xc9, 0x77, 0x30, 0x1f, 0xdc, 0xc7, 0xc0, 0x34, 0x3b, 0x30, 0x5d, 0x71, 0xcf, 0x73, 0x18, 0x6a, 0x63, 0xc8, 0xdb, 0xdd, 0x6b, 0x45, 0x4a, 0xbe, 0x83, 0x69, 0x6f,
0xc0, 0x2c, 0xdd, 0xf4, 0x9f, 0x66, 0x94, 0x68, 0x79, 0x05, 0x27, 0x17, 0x4d, 0x13, 0x7b, 0xf6, 0x06, 0x7b, 0xa6, 0xd9, 0x81, 0xe9, 0x02, 0x26, 0x69, 0x6f, 0xfe, 0xf4, 0x46, 0x89, 0x96, 0x97,
0x63, 0xea, 0xcf, 0x93, 0xed, 0xcf, 0x93, 0xbf, 0x3a, 0x90, 0x15, 0x23, 0x32, 0xc8, 0x53, 0xcf, 0x70, 0x72, 0xb1, 0xd9, 0xc4, 0x9a, 0xdd, 0x33, 0x75, 0x2b, 0xc0, 0xf6, 0x2b, 0xc0, 0x5f, 0x1d,
0x01, 0xa3, 0x86, 0x69, 0xf2, 0x07, 0x83, 0x27, 0x0a, 0x6f, 0x1f, 0xd0, 0xff, 0x3f, 0x0d, 0xff, 0xc8, 0x8a, 0x01, 0x19, 0xe4, 0xa9, 0x66, 0x8f, 0x51, 0xfd, 0x34, 0xf9, 0x83, 0xc1, 0x13, 0x85,
0xf2, 0xd9, 0xd5, 0xf9, 0xa7, 0x3a, 0xac, 0x37, 0xd5, 0xc2, 0xb4, 0x37, 0xcb, 0xb2, 0x34, 0x76, 0x37, 0xf7, 0xa8, 0xff, 0x40, 0x8f, 0xbf, 0x78, 0x76, 0x79, 0xfe, 0x69, 0x1d, 0x56, 0x6d, 0x35,
0x69, 0xd6, 0xba, 0xb6, 0x65, 0xb9, 0xa4, 0xb7, 0x55, 0x47, 0xf4, 0x4b, 0x28, 0x7f, 0x05, 0x00, 0x33, 0xf5, 0xf5, 0xbc, 0x2c, 0x8d, 0x9d, 0x9b, 0x95, 0x5e, 0xdb, 0xb2, 0x9c, 0xd3, 0xdd, 0xaa,
0x00, 0xff, 0xff, 0x1b, 0xce, 0xc2, 0x14, 0x23, 0x04, 0x00, 0x00, 0x23, 0xfa, 0xed, 0x94, 0xbf, 0x02, 0x00, 0x00, 0xff, 0xff, 0x57, 0xdf, 0x86, 0xd3, 0x87, 0x04,
0x00, 0x00,
} }
...@@ -104,6 +104,7 @@ const ( ...@@ -104,6 +104,7 @@ const (
TyLogGenesisDeposit = 12 TyLogGenesisDeposit = 12
TyLogRollback = 13 TyLogRollback = 13
TyLogMint = 14 TyLogMint = 14
TyLogBurn = 15
) )
//SystemLog 系统log日志 //SystemLog 系统log日志
...@@ -121,6 +122,8 @@ var SystemLog = map[int64]*LogInfo{ ...@@ -121,6 +122,8 @@ var SystemLog = map[int64]*LogInfo{
TyLogGenesisTransfer: {reflect.TypeOf(ReceiptAccountTransfer{}), "LogGenesisTransfer"}, TyLogGenesisTransfer: {reflect.TypeOf(ReceiptAccountTransfer{}), "LogGenesisTransfer"},
TyLogGenesisDeposit: {reflect.TypeOf(ReceiptAccountTransfer{}), "LogGenesisDeposit"}, TyLogGenesisDeposit: {reflect.TypeOf(ReceiptAccountTransfer{}), "LogGenesisDeposit"},
TyLogRollback: {reflect.TypeOf(LocalDBSet{}), "LogRollback"}, TyLogRollback: {reflect.TypeOf(LocalDBSet{}), "LogRollback"},
TyLogMint: {reflect.TypeOf(ReceiptAccountMint{}), "LogMint"},
TyLogBurn: {reflect.TypeOf(ReceiptAccountBurn{}), "LogBurn"},
} }
//exec type //exec type
......
...@@ -41,6 +41,11 @@ message ReceiptAccountMint { ...@@ -41,6 +41,11 @@ message ReceiptAccountMint {
Account current = 2; Account current = 2;
} }
message ReceiptAccountBurn {
Account prev = 1;
Account current = 2;
}
//查询一个地址列表在某个执行器中余额 //查询一个地址列表在某个执行器中余额
message ReqBalance { message ReqBalance {
//地址列表 //地址列表
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment