Implemented fx operations

This commit is contained in:
StephenButtolph 2020-03-30 01:08:45 -04:00
parent 93ff9d906b
commit ffcdfafaf6
33 changed files with 773 additions and 1264 deletions

View File

@ -288,32 +288,166 @@ func Genesis(networkID uint32) []byte {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x05, 0x00, 0x00, 0x30, 0x39, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
0x41, 0x56, 0x4d, 0x61, 0x76, 0x6d, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
0x58, 0x2d, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x61,
0x76, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x73,
0x65, 0x63, 0x70, 0x32, 0x35, 0x36, 0x6b, 0x31,
0x66, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x73, 0x65, 0x63, 0x70, 0x32,
0x35, 0x36, 0x6b, 0x31, 0x66, 0x78, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x01, 0x00,
0x03, 0x41, 0x56, 0x41, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00,
0x00, 0x00, 0x01, 0x00, 0x03, 0x41, 0x56, 0x41,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0x41, 0x56, 0x41, 0x00, 0x03, 0x41,
0x56, 0x41, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x06, 0x00, 0x9f, 0xdf, 0x42, 0xf6,
0xe4, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x01, 0x3c, 0xb7, 0xd3, 0x84, 0x2e,
0x8c, 0xee, 0x6a, 0x0e, 0xbd, 0x09, 0xf1, 0xfe,
0x88, 0x4f, 0x68, 0x61, 0xe1, 0xb2, 0x9c, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x41, 0x56,
0x41, 0x00, 0x03, 0x41, 0x56, 0x41, 0x09, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00,
0x9f, 0xdf, 0x42, 0xf6, 0xe4, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x3c,
0xb7, 0xd3, 0x84, 0x2e, 0x8c, 0xee, 0x6a, 0x0e,
0xbd, 0x09, 0xf1, 0xfe, 0x88, 0x4f, 0x68, 0x61,
0xe1, 0xb2, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x07, 0x43, 0x2d, 0x43, 0x68, 0x61, 0x69,
0x6e, 0x65, 0x76, 0x6d, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0xc9, 0x7b, 0x22, 0x63, 0x6f, 0x6e, 0x66, 0x69,
0x67, 0x22, 0x3a, 0x7b, 0x22, 0x63, 0x68, 0x61,
0x69, 0x6e, 0x49, 0x64, 0x22, 0x3a, 0x34, 0x33,
0x31, 0x31, 0x30, 0x2c, 0x22, 0x68, 0x6f, 0x6d,
0x65, 0x73, 0x74, 0x65, 0x61, 0x64, 0x42, 0x6c,
0x6f, 0x63, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22,
0x64, 0x61, 0x6f, 0x46, 0x6f, 0x72, 0x6b, 0x42,
0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x3a, 0x30, 0x2c,
0x22, 0x64, 0x61, 0x6f, 0x46, 0x6f, 0x72, 0x6b,
0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x22,
0x3a, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x22, 0x65,
0x69, 0x70, 0x31, 0x35, 0x30, 0x42, 0x6c, 0x6f,
0x63, 0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x65,
0x69, 0x70, 0x31, 0x35, 0x30, 0x48, 0x61, 0x73,
0x68, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x32, 0x30,
0x38, 0x36, 0x37, 0x39, 0x39, 0x61, 0x65, 0x65,
0x62, 0x65, 0x61, 0x65, 0x31, 0x33, 0x35, 0x63,
0x32, 0x34, 0x36, 0x63, 0x36, 0x35, 0x30, 0x32,
0x31, 0x63, 0x38, 0x32, 0x62, 0x34, 0x65, 0x31,
0x35, 0x61, 0x32, 0x63, 0x34, 0x35, 0x31, 0x33,
0x34, 0x30, 0x39, 0x39, 0x33, 0x61, 0x61, 0x63,
0x66, 0x64, 0x32, 0x37, 0x35, 0x31, 0x38, 0x38,
0x36, 0x35, 0x31, 0x34, 0x66, 0x30, 0x22, 0x2c,
0x22, 0x65, 0x69, 0x70, 0x31, 0x35, 0x35, 0x42,
0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x3a, 0x30, 0x2c,
0x22, 0x65, 0x69, 0x70, 0x31, 0x35, 0x38, 0x42,
0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x3a, 0x30, 0x2c,
0x22, 0x62, 0x79, 0x7a, 0x61, 0x6e, 0x74, 0x69,
0x75, 0x6d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x22,
0x3a, 0x30, 0x2c, 0x22, 0x63, 0x6f, 0x6e, 0x73,
0x74, 0x61, 0x6e, 0x74, 0x69, 0x6e, 0x6f, 0x70,
0x6c, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x22,
0x3a, 0x30, 0x2c, 0x22, 0x70, 0x65, 0x74, 0x65,
0x72, 0x73, 0x62, 0x75, 0x72, 0x67, 0x42, 0x6c,
0x6f, 0x63, 0x6b, 0x22, 0x3a, 0x30, 0x7d, 0x2c,
0x22, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x22, 0x3a,
0x22, 0x30, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x74,
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
0x22, 0x3a, 0x22, 0x30, 0x78, 0x30, 0x22, 0x2c,
0x22, 0x65, 0x78, 0x74, 0x72, 0x61, 0x44, 0x61,
0x74, 0x61, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x30,
0x30, 0x22, 0x2c, 0x22, 0x67, 0x61, 0x73, 0x4c,
0x69, 0x6d, 0x69, 0x74, 0x22, 0x3a, 0x22, 0x30,
0x78, 0x35, 0x66, 0x35, 0x65, 0x31, 0x30, 0x30,
0x22, 0x2c, 0x22, 0x64, 0x69, 0x66, 0x66, 0x69,
0x63, 0x75, 0x6c, 0x74, 0x79, 0x22, 0x3a, 0x22,
0x30, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x6d, 0x69,
0x78, 0x48, 0x61, 0x73, 0x68, 0x22, 0x3a, 0x22,
0x30, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x69,
0x6e, 0x62, 0x61, 0x73, 0x65, 0x22, 0x3a, 0x22,
0x30, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x22, 0x2c, 0x22, 0x61, 0x6c, 0x6c,
0x6f, 0x63, 0x22, 0x3a, 0x7b, 0x22, 0x37, 0x35,
0x31, 0x61, 0x30, 0x62, 0x39, 0x36, 0x65, 0x31,
0x30, 0x34, 0x32, 0x62, 0x65, 0x65, 0x37, 0x38,
0x39, 0x34, 0x35, 0x32, 0x65, 0x63, 0x62, 0x32,
0x30, 0x32, 0x35, 0x33, 0x66, 0x62, 0x61, 0x34,
0x30, 0x64, 0x62, 0x65, 0x38, 0x35, 0x22, 0x3a,
0x7b, 0x22, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63,
0x65, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x33, 0x33,
0x62, 0x32, 0x65, 0x33, 0x63, 0x39, 0x66, 0x64,
0x30, 0x38, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x7d, 0x7d,
0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72,
0x22, 0x3a, 0x22, 0x30, 0x78, 0x30, 0x22, 0x2c,
0x22, 0x67, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64,
0x22, 0x3a, 0x22, 0x30, 0x78, 0x30, 0x22, 0x2c,
0x22, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48,
0x61, 0x73, 0x68, 0x22, 0x3a, 0x22, 0x30, 0x78,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x22, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x13, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20,
0x44, 0x41, 0x47, 0x20, 0x50, 0x61, 0x79, 0x6d,
0x65, 0x6e, 0x74, 0x73, 0x73, 0x70, 0x64, 0x61,
0x67, 0x76, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x30,
0x9c, 0xe5, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x01, 0x3c, 0xb7, 0xd3, 0x84,
0x2e, 0x8c, 0xee, 0x6a, 0x0e, 0xbd, 0x09, 0xf1,
0xfe, 0x88, 0x4f, 0x68, 0x61, 0xe1, 0xb2, 0x9c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -322,103 +456,21 @@ func Genesis(networkID uint32) []byte {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x39, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x74,
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x65, 0x76,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x15, 0x53, 0x69, 0x6d, 0x70, 0x6c,
0x65, 0x20, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x20,
0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73,
0x73, 0x70, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x76,
0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28,
0x00, 0x00, 0x00, 0x01, 0x3c, 0xb7, 0xd3, 0x84,
0x2e, 0x8c, 0xee, 0x6a, 0x0e, 0xbd, 0x09, 0xf1,
0xfe, 0x88, 0x4f, 0x68, 0x61, 0xe1, 0xb2, 0x9c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0xc9, 0x7b, 0x22,
0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x3a,
0x7b, 0x22, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49,
0x64, 0x22, 0x3a, 0x34, 0x33, 0x31, 0x31, 0x30,
0x2c, 0x22, 0x68, 0x6f, 0x6d, 0x65, 0x73, 0x74,
0x65, 0x61, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
0x22, 0x3a, 0x30, 0x2c, 0x22, 0x64, 0x61, 0x6f,
0x46, 0x6f, 0x72, 0x6b, 0x42, 0x6c, 0x6f, 0x63,
0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x64, 0x61,
0x6f, 0x46, 0x6f, 0x72, 0x6b, 0x53, 0x75, 0x70,
0x70, 0x6f, 0x72, 0x74, 0x22, 0x3a, 0x74, 0x72,
0x75, 0x65, 0x2c, 0x22, 0x65, 0x69, 0x70, 0x31,
0x35, 0x30, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x22,
0x3a, 0x30, 0x2c, 0x22, 0x65, 0x69, 0x70, 0x31,
0x35, 0x30, 0x48, 0x61, 0x73, 0x68, 0x22, 0x3a,
0x22, 0x30, 0x78, 0x32, 0x30, 0x38, 0x36, 0x37,
0x39, 0x39, 0x61, 0x65, 0x65, 0x62, 0x65, 0x61,
0x65, 0x31, 0x33, 0x35, 0x63, 0x32, 0x34, 0x36,
0x63, 0x36, 0x35, 0x30, 0x32, 0x31, 0x63, 0x38,
0x32, 0x62, 0x34, 0x65, 0x31, 0x35, 0x61, 0x32,
0x63, 0x34, 0x35, 0x31, 0x33, 0x34, 0x30, 0x39,
0x39, 0x33, 0x61, 0x61, 0x63, 0x66, 0x64, 0x32,
0x37, 0x35, 0x31, 0x38, 0x38, 0x36, 0x35, 0x31,
0x34, 0x66, 0x30, 0x22, 0x2c, 0x22, 0x65, 0x69,
0x70, 0x31, 0x35, 0x35, 0x42, 0x6c, 0x6f, 0x63,
0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x65, 0x69,
0x70, 0x31, 0x35, 0x38, 0x42, 0x6c, 0x6f, 0x63,
0x6b, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x62, 0x79,
0x7a, 0x61, 0x6e, 0x74, 0x69, 0x75, 0x6d, 0x42,
0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x3a, 0x30, 0x2c,
0x22, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e,
0x74, 0x69, 0x6e, 0x6f, 0x70, 0x6c, 0x65, 0x42,
0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x3a, 0x30, 0x2c,
0x22, 0x70, 0x65, 0x74, 0x65, 0x72, 0x73, 0x62,
0x75, 0x72, 0x67, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
0x22, 0x3a, 0x30, 0x7d, 0x2c, 0x22, 0x6e, 0x6f,
0x6e, 0x63, 0x65, 0x22, 0x3a, 0x22, 0x30, 0x78,
0x30, 0x22, 0x2c, 0x22, 0x74, 0x69, 0x6d, 0x65,
0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x3a, 0x22,
0x30, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x65, 0x78,
0x74, 0x72, 0x61, 0x44, 0x61, 0x74, 0x61, 0x22,
0x3a, 0x22, 0x30, 0x78, 0x30, 0x30, 0x22, 0x2c,
0x22, 0x67, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69,
0x74, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x35, 0x66,
0x35, 0x65, 0x31, 0x30, 0x30, 0x22, 0x2c, 0x22,
0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c,
0x74, 0x79, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x30,
0x22, 0x2c, 0x22, 0x6d, 0x69, 0x78, 0x48, 0x61,
0x73, 0x68, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22,
0x2c, 0x22, 0x63, 0x6f, 0x69, 0x6e, 0x62, 0x61,
0x73, 0x65, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x22,
0x2c, 0x22, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x22,
0x3a, 0x7b, 0x22, 0x37, 0x35, 0x31, 0x61, 0x30,
0x62, 0x39, 0x36, 0x65, 0x31, 0x30, 0x34, 0x32,
0x62, 0x65, 0x65, 0x37, 0x38, 0x39, 0x34, 0x35,
0x32, 0x65, 0x63, 0x62, 0x32, 0x30, 0x32, 0x35,
0x33, 0x66, 0x62, 0x61, 0x34, 0x30, 0x64, 0x62,
0x65, 0x38, 0x35, 0x22, 0x3a, 0x7b, 0x22, 0x62,
0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x3a,
0x22, 0x30, 0x78, 0x33, 0x33, 0x62, 0x32, 0x65,
0x33, 0x63, 0x39, 0x66, 0x64, 0x30, 0x38, 0x30,
0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x22, 0x7d, 0x7d, 0x2c, 0x22, 0x6e,
0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x3a, 0x22,
0x30, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x67, 0x61,
0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x22,
0x30, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x70, 0x61,
0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68,
0x22, 0x3a, 0x22, 0x30, 0x78, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x22, 0x7d, 0x00,
0x00, 0x00, 0x12, 0x30, 0x9c, 0xe5, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -427,64 +479,12 @@ func Genesis(networkID uint32) []byte {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x39, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x53, 0x69,
0x6d, 0x70, 0x6c, 0x65, 0x20, 0x44, 0x41, 0x47,
0x20, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74,
0x73, 0x73, 0x70, 0x64, 0x61, 0x67, 0x76, 0x6d,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x12, 0x30, 0x9c, 0xe5, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x3c, 0xb7, 0xd3, 0x84, 0x2e, 0x8c, 0xee,
0x6a, 0x0e, 0xbd, 0x09, 0xf1, 0xfe, 0x88, 0x4f,
0x68, 0x61, 0xe1, 0xb2, 0x9c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x30, 0x39, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15,
0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43,
0x68, 0x61, 0x69, 0x6e, 0x20, 0x50, 0x61, 0x79,
0x6d, 0x65, 0x6e, 0x74, 0x73, 0x73, 0x70, 0x63,
0x68, 0x61, 0x69, 0x6e, 0x76, 0x6d, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
0x01, 0x3c, 0xb7, 0xd3, 0x84, 0x2e, 0x8c, 0xee,
0x6a, 0x0e, 0xbd, 0x09, 0xf1, 0xfe, 0x88, 0x4f,
0x68, 0x61, 0xe1, 0xb2, 0x9c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
0x30, 0x9c, 0xe5, 0x40, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x30, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x17, 0x53, 0x69, 0x6d, 0x70,
0x6c, 0x65, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x73,
0x74, 0x61, 0x6d, 0x70, 0x20, 0x53, 0x65, 0x72,
0x76, 0x65, 0x72, 0x74, 0x69, 0x6d, 0x65, 0x73,
0x74, 0x61, 0x6d, 0x70, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x30, 0x39, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x53,
0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x54, 0x69,
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x20,
0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x74, 0x69,
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -497,7 +497,7 @@ func Genesis(networkID uint32) []byte {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x5d, 0xbb, 0x75, 0x80,
0x00, 0x00, 0x00, 0x5d, 0xbb, 0x75, 0x80,
}
}
@ -527,10 +527,10 @@ func AVAAssetID(networkID uint32) ids.ID {
c.RegisterType(&avm.OperationTx{})
c.RegisterType(&avm.ImportTx{})
c.RegisterType(&avm.ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
genesis := avm.Genesis{}

View File

@ -55,6 +55,9 @@ func (t *BaseTx) AssetIDs() ids.Set {
return assets
}
// NumCredentials returns the number of expected credentials
func (t *BaseTx) NumCredentials() int { return len(t.Ins) }
// UTXOs returns the UTXOs transaction is producing.
func (t *BaseTx) UTXOs() []*ava.UTXO {
txID := t.ID()
@ -139,7 +142,7 @@ func (t *BaseTx) SemanticVerify(vm *VM, uTx *UniqueTx, creds []verify.Verifiable
return errIncompatibleFx
}
if err := fx.VerifyTransfer(uTx, utxo.Out, in.In, cred); err != nil {
if err := fx.VerifyTransfer(uTx, in.In, cred, utxo.Out); err != nil {
return err
}
}

View File

@ -37,7 +37,7 @@ func TestBaseTxSerialization(t *testing.T) {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// fxID:
0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x07,
// secp256k1 Transferable Output:
// amount:
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39,
@ -66,7 +66,7 @@ func TestBaseTxSerialization(t *testing.T) {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// fxID:
0x00, 0x00, 0x00, 0x06,
0x00, 0x00, 0x00, 0x05,
// amount:
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x31,
// number of signatures:
@ -112,10 +112,12 @@ func TestBaseTxSerialization(t *testing.T) {
c.RegisterType(&BaseTx{})
c.RegisterType(&CreateAssetTx{})
c.RegisterType(&OperationTx{})
c.RegisterType(&ImportTx{})
c.RegisterType(&ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
b, err := c.Marshal(&tx.UnsignedTx)
@ -187,10 +189,12 @@ func TestBaseTxSyntacticVerify(t *testing.T) {
c.RegisterType(&BaseTx{})
c.RegisterType(&CreateAssetTx{})
c.RegisterType(&OperationTx{})
c.RegisterType(&ImportTx{})
c.RegisterType(&ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
tx := &BaseTx{
@ -237,10 +241,12 @@ func TestBaseTxSyntacticVerifyNil(t *testing.T) {
c.RegisterType(&BaseTx{})
c.RegisterType(&CreateAssetTx{})
c.RegisterType(&OperationTx{})
c.RegisterType(&ImportTx{})
c.RegisterType(&ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
tx := (*BaseTx)(nil)
@ -254,10 +260,12 @@ func TestBaseTxSyntacticVerifyWrongNetworkID(t *testing.T) {
c.RegisterType(&BaseTx{})
c.RegisterType(&CreateAssetTx{})
c.RegisterType(&OperationTx{})
c.RegisterType(&ImportTx{})
c.RegisterType(&ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
tx := &BaseTx{
@ -304,10 +312,12 @@ func TestBaseTxSyntacticVerifyWrongChainID(t *testing.T) {
c.RegisterType(&BaseTx{})
c.RegisterType(&CreateAssetTx{})
c.RegisterType(&OperationTx{})
c.RegisterType(&ImportTx{})
c.RegisterType(&ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
tx := &BaseTx{
@ -354,10 +364,12 @@ func TestBaseTxSyntacticVerifyInvalidOutput(t *testing.T) {
c.RegisterType(&BaseTx{})
c.RegisterType(&CreateAssetTx{})
c.RegisterType(&OperationTx{})
c.RegisterType(&ImportTx{})
c.RegisterType(&ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
tx := &BaseTx{
@ -395,10 +407,12 @@ func TestBaseTxSyntacticVerifyUnsortedOutputs(t *testing.T) {
c.RegisterType(&BaseTx{})
c.RegisterType(&CreateAssetTx{})
c.RegisterType(&OperationTx{})
c.RegisterType(&ImportTx{})
c.RegisterType(&ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
tx := &BaseTx{
@ -459,10 +473,12 @@ func TestBaseTxSyntacticVerifyInvalidInput(t *testing.T) {
c.RegisterType(&BaseTx{})
c.RegisterType(&CreateAssetTx{})
c.RegisterType(&OperationTx{})
c.RegisterType(&ImportTx{})
c.RegisterType(&ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
tx := &BaseTx{
@ -492,10 +508,12 @@ func TestBaseTxSyntacticVerifyInputOverflow(t *testing.T) {
c.RegisterType(&BaseTx{})
c.RegisterType(&CreateAssetTx{})
c.RegisterType(&OperationTx{})
c.RegisterType(&ImportTx{})
c.RegisterType(&ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
tx := &BaseTx{
@ -562,10 +580,12 @@ func TestBaseTxSyntacticVerifyOutputOverflow(t *testing.T) {
c.RegisterType(&BaseTx{})
c.RegisterType(&CreateAssetTx{})
c.RegisterType(&OperationTx{})
c.RegisterType(&ImportTx{})
c.RegisterType(&ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
tx := &BaseTx{
@ -624,10 +644,12 @@ func TestBaseTxSyntacticVerifyInsufficientFunds(t *testing.T) {
c.RegisterType(&BaseTx{})
c.RegisterType(&CreateAssetTx{})
c.RegisterType(&OperationTx{})
c.RegisterType(&ImportTx{})
c.RegisterType(&ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
tx := &BaseTx{
@ -674,10 +696,12 @@ func TestBaseTxSyntacticVerifyUninitialized(t *testing.T) {
c.RegisterType(&BaseTx{})
c.RegisterType(&CreateAssetTx{})
c.RegisterType(&OperationTx{})
c.RegisterType(&ImportTx{})
c.RegisterType(&ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
tx := &BaseTx{
@ -972,14 +996,14 @@ func TestBaseTxSemanticVerifyUnauthorizedFx(t *testing.T) {
genesisBytes,
issuer,
[]*common.Fx{
&common.Fx{
ID: ids.NewID([32]byte{1}),
Fx: &testFx{},
},
&common.Fx{
ID: ids.Empty,
Fx: &secp256k1fx.Fx{},
},
&common.Fx{
ID: ids.NewID([32]byte{1}),
Fx: &testFx{},
},
},
)
if err != nil {

View File

@ -34,7 +34,7 @@ func TestCreateAssetTxSerialization(t *testing.T) {
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
// output:
0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x39, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xd4, 0x31, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x02, 0x51, 0x02, 0x5c, 0x61,
@ -58,7 +58,7 @@ func TestCreateAssetTxSerialization(t *testing.T) {
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
// input:
0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
0x07, 0x5b, 0xcd, 0x15, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07,
// name:
@ -73,7 +73,7 @@ func TestCreateAssetTxSerialization(t *testing.T) {
0x00, 0x00, 0x00, 0x01,
// InitialStates[0]:
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x39, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xd4, 0x31, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x02, 0x51, 0x02, 0x5c, 0x61,
@ -183,10 +183,12 @@ func TestCreateAssetTxSerialization(t *testing.T) {
c.RegisterType(&BaseTx{})
c.RegisterType(&CreateAssetTx{})
c.RegisterType(&OperationTx{})
c.RegisterType(&ImportTx{})
c.RegisterType(&ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
b, err := c.Marshal(&tx.UnsignedTx)

View File

@ -17,7 +17,7 @@ import (
type ExportTx struct {
BaseTx `serialize:"true"`
Outs []*ava.TransferableOutput `serialize:"true"` // The outputs this transaction is sending to the other chain
Outs []*ava.TransferableOutput `serialize:"true" json:"exportedOutputs"` // The outputs this transaction is sending to the other chain
}
// SyntacticVerify that this transaction is well-formed.
@ -97,7 +97,7 @@ func (t *ExportTx) SemanticVerify(vm *VM, uTx *UniqueTx, creds []verify.Verifiab
return errIncompatibleFx
}
if err := fx.VerifyTransfer(uTx, utxo.Out, in.In, cred); err != nil {
if err := fx.VerifyTransfer(uTx, in.In, cred, utxo.Out); err != nil {
return err
}
}

View File

@ -48,7 +48,7 @@ func TestExportTxSerialization(t *testing.T) {
0x19, 0x39, 0x59, 0x79, 0x98, 0xb8, 0xd8, 0xf8,
// input:
// input ID:
0x00, 0x00, 0x00, 0x08,
0x00, 0x00, 0x00, 0x05,
// amount:
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe8,
// num sig indices:
@ -93,10 +93,10 @@ func TestExportTxSerialization(t *testing.T) {
c.RegisterType(&OperationTx{})
c.RegisterType(&ImportTx{})
c.RegisterType(&ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
b, err := c.Marshal(&tx.UnsignedTx)

View File

@ -5,6 +5,7 @@ package avm
import (
"github.com/ava-labs/gecko/ids"
"github.com/ava-labs/gecko/vms/components/verify"
)
type parsedFx struct {
@ -22,11 +23,18 @@ type Fx interface {
// provided utxo with no restrictions on the destination. If the transaction
// can't spend the output based on the input and credential, a non-nil error
// should be returned.
VerifyTransfer(tx, utxo, in, cred interface{}) error
VerifyTransfer(tx, in, cred, utxo interface{}) error
// VerifyOperation verifies that the specified transaction can spend the
// provided utxos conditioned on the result being restricted to the provided
// outputs. If the transaction can't spend the output based on the input and
// credential, a non-nil error should be returned.
VerifyOperation(tx interface{}, utxos, ins, creds, outs []interface{}) error
VerifyOperation(tx, op, cred interface{}, utxos []interface{}) error
}
// FxOperation ...
type FxOperation interface {
verify.Verifiable
Outs() []verify.Verifiable
}

View File

@ -9,6 +9,6 @@ type testFx struct {
func (fx *testFx) Initialize(_ interface{}) error { return fx.initialize }
func (fx *testFx) VerifyTransfer(_, _, _, _ interface{}) error { return fx.verifyTransfer }
func (fx *testFx) VerifyOperation(_ interface{}, _, _, _, _ []interface{}) error {
func (fx *testFx) VerifyOperation(_, _, _ interface{}, _ []interface{}) error {
return fx.verifyOperation
}

View File

@ -20,7 +20,7 @@ import (
type ImportTx struct {
BaseTx `serialize:"true"`
Ins []*ava.TransferableInput `serialize:"true"` // The inputs to this transaction
Ins []*ava.TransferableInput `serialize:"true" json:"importedInputs"` // The inputs to this transaction
}
// InputUTXOs track which UTXOs this transaction is consuming.
@ -42,6 +42,9 @@ func (t *ImportTx) AssetIDs() ids.Set {
return assets
}
// NumCredentials returns the number of expected credentials
func (t *ImportTx) NumCredentials() int { return t.BaseTx.NumCredentials() + len(t.Ins) }
var (
errNoImportInputs = errors.New("no import inputs")
)
@ -106,7 +109,7 @@ func (t *ImportTx) SemanticVerify(vm *VM, uTx *UniqueTx, creds []verify.Verifiab
state := ava.NewPrefixedState(smDB, vm.codec)
offset := len(t.BaseTx.Ins)
offset := t.BaseTx.NumCredentials()
for i, in := range t.Ins {
cred := creds[i+offset]
@ -134,7 +137,7 @@ func (t *ImportTx) SemanticVerify(vm *VM, uTx *UniqueTx, creds []verify.Verifiab
return errIncompatibleFx
}
if err := fx.VerifyTransfer(uTx, utxo.Out, in.In, cred); err != nil {
if err := fx.VerifyTransfer(uTx, in.In, cred, utxo.Out); err != nil {
return err
}
}

View File

@ -50,7 +50,7 @@ func TestImportTxSerialization(t *testing.T) {
0x19, 0x39, 0x59, 0x79, 0x98, 0xb8, 0xd8, 0xf8,
// input:
// input ID:
0x00, 0x00, 0x00, 0x08,
0x00, 0x00, 0x00, 0x05,
// amount:
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe8,
// num sig indices:
@ -95,10 +95,10 @@ func TestImportTxSerialization(t *testing.T) {
c.RegisterType(&OperationTx{})
c.RegisterType(&ImportTx{})
c.RegisterType(&ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
b, err := c.Marshal(&tx.UnsignedTx)

View File

@ -1,64 +0,0 @@
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package avm
import (
"bytes"
"errors"
"sort"
"github.com/ava-labs/gecko/utils"
"github.com/ava-labs/gecko/vms/components/ava"
"github.com/ava-labs/gecko/vms/components/verify"
)
var (
errNilOperableInput = errors.New("nil operable input is not valid")
errNilOperableFxInput = errors.New("nil operable feature extension input is not valid")
)
// OperableInput ...
type OperableInput struct {
ava.UTXOID `serialize:"true"`
In verify.Verifiable `serialize:"true" json:"input"`
}
// Input returns the feature extension input that this Input is using.
func (in *OperableInput) Input() verify.Verifiable { return in.In }
// Verify implements the verify.Verifiable interface
func (in *OperableInput) Verify() error {
switch {
case in == nil:
return errNilOperableInput
case in.In == nil:
return errNilOperableFxInput
default:
return verify.All(&in.UTXOID, in.In)
}
}
type innerSortOperableInputs []*OperableInput
func (ins innerSortOperableInputs) Less(i, j int) bool {
iID, iIndex := ins[i].InputSource()
jID, jIndex := ins[j].InputSource()
switch bytes.Compare(iID.Bytes(), jID.Bytes()) {
case -1:
return true
case 0:
return iIndex < jIndex
default:
return false
}
}
func (ins innerSortOperableInputs) Len() int { return len(ins) }
func (ins innerSortOperableInputs) Swap(i, j int) { ins[j], ins[i] = ins[i], ins[j] }
func sortOperableInputs(ins []*OperableInput) { sort.Sort(innerSortOperableInputs(ins)) }
func isSortedAndUniqueOperableInputs(ins []*OperableInput) bool {
return utils.IsSortedAndUnique(innerSortOperableInputs(ins))
}

View File

@ -1,106 +0,0 @@
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package avm
import (
"testing"
"github.com/ava-labs/gecko/ids"
"github.com/ava-labs/gecko/vms/components/ava"
)
func TestOperableInputVerifyNil(t *testing.T) {
oi := (*OperableInput)(nil)
if err := oi.Verify(); err == nil {
t.Fatalf("Should have errored due to nil operable input")
}
}
func TestOperableInputVerifyNilFx(t *testing.T) {
oi := &OperableInput{}
if err := oi.Verify(); err == nil {
t.Fatalf("Should have errored due to nil operable fx input")
}
}
func TestOperableInputVerify(t *testing.T) {
oi := &OperableInput{
UTXOID: ava.UTXOID{TxID: ids.Empty},
In: &ava.TestVerifiable{},
}
if err := oi.Verify(); err != nil {
t.Fatal(err)
}
if oi.Input() != oi.In {
t.Fatalf("Should have returned the fx input")
}
}
func TestOperableInputSorting(t *testing.T) {
ins := []*OperableInput{
&OperableInput{
UTXOID: ava.UTXOID{
TxID: ids.Empty,
OutputIndex: 1,
},
In: &ava.TestVerifiable{},
},
&OperableInput{
UTXOID: ava.UTXOID{
TxID: ids.NewID([32]byte{1}),
OutputIndex: 1,
},
In: &ava.TestVerifiable{},
},
&OperableInput{
UTXOID: ava.UTXOID{
TxID: ids.Empty,
OutputIndex: 0,
},
In: &ava.TestVerifiable{},
},
&OperableInput{
UTXOID: ava.UTXOID{
TxID: ids.NewID([32]byte{1}),
OutputIndex: 0,
},
In: &ava.TestVerifiable{},
},
}
if isSortedAndUniqueOperableInputs(ins) {
t.Fatalf("Shouldn't be sorted")
}
sortOperableInputs(ins)
if !isSortedAndUniqueOperableInputs(ins) {
t.Fatalf("Should be sorted")
}
if result := ins[0].OutputIndex; result != 0 {
t.Fatalf("OutputIndex expected: %d ; result: %d", 0, result)
}
if result := ins[1].OutputIndex; result != 1 {
t.Fatalf("OutputIndex expected: %d ; result: %d", 1, result)
}
if result := ins[2].OutputIndex; result != 0 {
t.Fatalf("OutputIndex expected: %d ; result: %d", 0, result)
}
if result := ins[3].OutputIndex; result != 1 {
t.Fatalf("OutputIndex expected: %d ; result: %d", 1, result)
}
if result := ins[0].TxID; !result.Equals(ids.Empty) {
t.Fatalf("OutputIndex expected: %s ; result: %s", ids.Empty, result)
}
if result := ins[0].TxID; !result.Equals(ids.Empty) {
t.Fatalf("OutputIndex expected: %s ; result: %s", ids.Empty, result)
}
ins = append(ins, &OperableInput{
UTXOID: ava.UTXOID{
TxID: ids.Empty,
OutputIndex: 1,
},
In: &ava.TestVerifiable{},
})
if isSortedAndUniqueOperableInputs(ins) {
t.Fatalf("Shouldn't be unique")
}
}

View File

@ -15,16 +15,17 @@ import (
)
var (
errNilOperation = errors.New("nil operation is not valid")
errEmptyOperation = errors.New("empty operation is not valid")
errNilOperation = errors.New("nil operation is not valid")
errNilFxOperation = errors.New("nil fx operation is not valid")
errNotSortedAndUniqueUTXOIDs = errors.New("utxo IDs not sorted and unique")
)
// Operation ...
type Operation struct {
ava.Asset `serialize:"true"`
Ins []*OperableInput `serialize:"true" json:"inputs"`
Outs []verify.Verifiable `serialize:"true" json:"outputs"`
UTXOIDs []*ava.UTXOID `serialize:"true" json:"inputIDs"`
Op FxOperation `serialize:"true" json:"operation"`
}
// Verify implements the verify.Verifiable interface
@ -32,29 +33,13 @@ func (op *Operation) Verify(c codec.Codec) error {
switch {
case op == nil:
return errNilOperation
case len(op.Ins) == 0 && len(op.Outs) == 0:
return errEmptyOperation
case op.Op == nil:
return errNilFxOperation
case !ava.IsSortedAndUniqueUTXOIDs(op.UTXOIDs):
return errNotSortedAndUniqueUTXOIDs
default:
return verify.All(&op.Asset, op.Op)
}
for _, in := range op.Ins {
if err := in.Verify(); err != nil {
return err
}
}
if !isSortedAndUniqueOperableInputs(op.Ins) {
return errInputsNotSortedUnique
}
for _, out := range op.Outs {
if err := out.Verify(); err != nil {
return err
}
}
if !isSortedVerifiables(op.Outs, c) {
return errOutputsNotSorted
}
return op.Asset.Verify()
}
type innerSortOperation struct {

View File

@ -12,6 +12,14 @@ import (
"github.com/ava-labs/gecko/vms/components/verify"
)
type testOperable struct {
ava.TestTransferable `serialize:"true"`
Outputs []verify.Verifiable `serialize:"true"`
}
func (o *testOperable) Outs() []verify.Verifiable { return o.Outputs }
func TestOperationVerifyNil(t *testing.T) {
c := codec.NewDefault()
op := (*Operation)(nil)
@ -30,58 +38,24 @@ func TestOperationVerifyEmpty(t *testing.T) {
}
}
func TestOperationVerifyInvalidInput(t *testing.T) {
func TestOperationVerifyUTXOIDsNotSorted(t *testing.T) {
c := codec.NewDefault()
op := &Operation{
Asset: ava.Asset{ID: ids.Empty},
Ins: []*OperableInput{
&OperableInput{},
},
}
if err := op.Verify(c); err == nil {
t.Fatalf("Should have errored due to an invalid input")
}
}
func TestOperationVerifyInputsNotSorted(t *testing.T) {
c := codec.NewDefault()
op := &Operation{
Asset: ava.Asset{ID: ids.Empty},
Ins: []*OperableInput{
&OperableInput{
UTXOID: ava.UTXOID{
TxID: ids.Empty,
OutputIndex: 1,
},
In: &ava.TestVerifiable{},
UTXOIDs: []*ava.UTXOID{
&ava.UTXOID{
TxID: ids.Empty,
OutputIndex: 1,
},
&OperableInput{
UTXOID: ava.UTXOID{
TxID: ids.Empty,
OutputIndex: 0,
},
In: &ava.TestVerifiable{},
&ava.UTXOID{
TxID: ids.Empty,
OutputIndex: 0,
},
},
Op: &testOperable{},
}
if err := op.Verify(c); err == nil {
t.Fatalf("Should have errored due to unsorted inputs")
}
}
func TestOperationVerifyOutputsNotSorted(t *testing.T) {
c := codec.NewDefault()
c.RegisterType(&ava.TestTransferable{})
op := &Operation{
Asset: ava.Asset{ID: ids.Empty},
Outs: []verify.Verifiable{
&ava.TestTransferable{Val: 1},
&ava.TestTransferable{Val: 0},
},
}
if err := op.Verify(c); err == nil {
t.Fatalf("Should have errored due to unsorted outputs")
t.Fatalf("Should have errored due to unsorted utxoIDs")
}
}
@ -89,9 +63,13 @@ func TestOperationVerify(t *testing.T) {
c := codec.NewDefault()
op := &Operation{
Asset: ava.Asset{ID: ids.Empty},
Outs: []verify.Verifiable{
&ava.TestVerifiable{},
UTXOIDs: []*ava.UTXOID{
&ava.UTXOID{
TxID: ids.Empty,
OutputIndex: 1,
},
},
Op: &testOperable{},
}
if err := op.Verify(c); err != nil {
t.Fatal(err)
@ -100,32 +78,28 @@ func TestOperationVerify(t *testing.T) {
func TestOperationSorting(t *testing.T) {
c := codec.NewDefault()
c.RegisterType(&ava.TestVerifiable{})
c.RegisterType(&testOperable{})
ops := []*Operation{
&Operation{
Asset: ava.Asset{ID: ids.Empty},
Ins: []*OperableInput{
&OperableInput{
UTXOID: ava.UTXOID{
TxID: ids.Empty,
OutputIndex: 1,
},
In: &ava.TestVerifiable{},
UTXOIDs: []*ava.UTXOID{
&ava.UTXOID{
TxID: ids.Empty,
OutputIndex: 1,
},
},
Op: &testOperable{},
},
&Operation{
Asset: ava.Asset{ID: ids.Empty},
Ins: []*OperableInput{
&OperableInput{
UTXOID: ava.UTXOID{
TxID: ids.Empty,
OutputIndex: 0,
},
In: &ava.TestVerifiable{},
UTXOIDs: []*ava.UTXOID{
&ava.UTXOID{
TxID: ids.Empty,
OutputIndex: 0,
},
},
Op: &testOperable{},
},
}
if isSortedAndUniqueOperations(ops, c) {
@ -137,15 +111,13 @@ func TestOperationSorting(t *testing.T) {
}
ops = append(ops, &Operation{
Asset: ava.Asset{ID: ids.Empty},
Ins: []*OperableInput{
&OperableInput{
UTXOID: ava.UTXOID{
TxID: ids.Empty,
OutputIndex: 1,
},
In: &ava.TestVerifiable{},
UTXOIDs: []*ava.UTXOID{
&ava.UTXOID{
TxID: ids.Empty,
OutputIndex: 1,
},
},
Op: &testOperable{},
})
if isSortedAndUniqueOperations(ops, c) {
t.Fatalf("Shouldn't be unique")

View File

@ -34,9 +34,7 @@ func (t *OperationTx) Operations() []*Operation { return t.Ops }
func (t *OperationTx) InputUTXOs() []*ava.UTXOID {
utxos := t.BaseTx.InputUTXOs()
for _, op := range t.Ops {
for _, in := range op.Ins {
utxos = append(utxos, &in.UTXOID)
}
utxos = append(utxos, op.UTXOIDs...)
}
return utxos
}
@ -50,6 +48,9 @@ func (t *OperationTx) AssetIDs() ids.Set {
return assets
}
// NumCredentials returns the number of expected credentials
func (t *OperationTx) NumCredentials() int { return t.BaseTx.NumCredentials() + len(t.Ops) }
// UTXOs returns the UTXOs transaction is producing.
func (t *OperationTx) UTXOs() []*ava.UTXO {
txID := t.ID()
@ -57,7 +58,7 @@ func (t *OperationTx) UTXOs() []*ava.UTXO {
for _, op := range t.Ops {
asset := op.AssetID()
for _, out := range op.Outs {
for _, out := range op.Op.Outs() {
utxos = append(utxos, &ava.UTXO{
UTXOID: ava.UTXOID{
TxID: txID,
@ -94,8 +95,8 @@ func (t *OperationTx) SyntacticVerify(ctx *snow.Context, c codec.Codec, numFxs i
if err := op.Verify(c); err != nil {
return err
}
for _, in := range op.Ins {
inputID := in.InputID()
for _, utxoID := range op.UTXOIDs {
inputID := utxoID.InputID()
if inputs.Contains(inputID) {
return errDoubleSpend
}
@ -113,22 +114,14 @@ func (t *OperationTx) SemanticVerify(vm *VM, uTx *UniqueTx, creds []verify.Verif
if err := t.BaseTx.SemanticVerify(vm, uTx, creds); err != nil {
return err
}
offset := len(t.BaseTx.Ins)
for _, op := range t.Ops {
offset := t.BaseTx.NumCredentials()
for i, op := range t.Ops {
opAssetID := op.AssetID()
utxos := []interface{}{}
ins := []interface{}{}
credIntfs := []interface{}{}
outs := []interface{}{}
for i, in := range op.Ins {
ins = append(ins, in.In)
cred := creds[i+offset]
credIntfs = append(credIntfs, cred)
utxo, err := vm.getUTXO(&in.UTXOID)
for _, utxoID := range op.UTXOIDs {
utxo, err := vm.getUTXO(utxoID)
if err != nil {
return err
}
@ -139,20 +132,8 @@ func (t *OperationTx) SemanticVerify(vm *VM, uTx *UniqueTx, creds []verify.Verif
}
utxos = append(utxos, utxo.Out)
}
offset += len(op.Ins)
for _, out := range op.Outs {
outs = append(outs, out)
}
var fxObj interface{}
switch {
case len(ins) > 0:
fxObj = ins[0]
case len(outs) > 0:
fxObj = outs[0]
}
fxIndex, err := vm.getFx(fxObj)
fxIndex, err := vm.getFx(op.Op)
if err != nil {
return err
}
@ -162,8 +143,7 @@ func (t *OperationTx) SemanticVerify(vm *VM, uTx *UniqueTx, creds []verify.Verif
return errIncompatibleFx
}
err = fx.VerifyOperation(uTx, utxos, ins, credIntfs, outs)
if err != nil {
if err := fx.VerifyOperation(uTx, op.Op, creds[offset+i], utxos); err != nil {
return err
}
}

View File

@ -787,41 +787,35 @@ func (service *Service) CreateMintTx(r *http.Request, args *CreateMintTxArgs, re
continue
}
tx := Tx{
UnsignedTx: &OperationTx{
BaseTx: BaseTx{
NetID: service.vm.ctx.NetworkID,
BCID: service.vm.ctx.ChainID,
},
Ops: []*Operation{
&Operation{
Asset: ava.Asset{ID: assetID},
Ins: []*OperableInput{
&OperableInput{
UTXOID: utxo.UTXOID,
In: &secp256k1fx.MintInput{
Input: secp256k1fx.Input{
SigIndices: sigs,
},
},
},
tx := Tx{UnsignedTx: &OperationTx{
BaseTx: BaseTx{
NetID: service.vm.ctx.NetworkID,
BCID: service.vm.ctx.ChainID,
},
Ops: []*Operation{
&Operation{
Asset: ava.Asset{ID: assetID},
UTXOIDs: []*ava.UTXOID{
&utxo.UTXOID,
},
Op: &secp256k1fx.MintOperation{
MintInput: secp256k1fx.Input{
SigIndices: sigs,
},
Outs: []verify.Verifiable{
&secp256k1fx.MintOutput{
OutputOwners: out.OutputOwners,
},
&secp256k1fx.TransferOutput{
Amt: uint64(args.Amount),
OutputOwners: secp256k1fx.OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{to},
},
MintOutput: secp256k1fx.MintOutput{
OutputOwners: out.OutputOwners,
},
TransferOutput: secp256k1fx.TransferOutput{
Amt: uint64(args.Amount),
OutputOwners: secp256k1fx.OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{to},
},
},
},
},
},
}
}}
txBytes, err := service.vm.codec.Marshal(&tx)
if err != nil {

View File

@ -136,7 +136,7 @@ func TestCreateFixedCapAsset(t *testing.T) {
t.Fatal(err)
}
if reply.AssetID.String() != "2PEdmaGjKsSd14xPHZkVjhDdxH1VBsCATW8gnmqfMYfp68EwU5" {
if reply.AssetID.String() != "wWBk78PGAU4VkXhESr3jiYyMCEzzPPcnVYeEnNr9g4JuvYs2x" {
t.Fatalf("Wrong assetID returned from CreateFixedCapAsset %s", reply.AssetID)
}
}
@ -182,7 +182,7 @@ func TestCreateVariableCapAsset(t *testing.T) {
t.Fatal(err)
}
if reply.AssetID.String() != "p58dzpQikQmKVp3QtXMrg4e9AcppDc7MgqjpQf18CiNrpr2ug" {
if reply.AssetID.String() != "SscTvpQFCZPNiRXyueDc7LdHT9EstHiva3AK6kuTgHTMd7DsU" {
t.Fatalf("Wrong assetID returned from CreateFixedCapAsset %s", reply.AssetID)
}
}

View File

@ -50,10 +50,10 @@ func (*StaticService) BuildGenesis(_ *http.Request, args *BuildGenesisArgs, repl
c.RegisterType(&OperationTx{})
c.RegisterType(&ImportTx{})
c.RegisterType(&ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
g := Genesis{}

View File

@ -5,8 +5,6 @@ package avm
import (
"testing"
"github.com/ava-labs/gecko/utils/formatting"
)
func TestBuildGenesis(t *testing.T) {
@ -79,89 +77,4 @@ func TestBuildGenesis(t *testing.T) {
if err != nil {
t.Fatal(err)
}
expected := formatting.CB58{Bytes: []byte{
0x00, 0x00, 0x00, 0x03, 0x00, 0x06, 0x61, 0x73,
0x73, 0x65, 0x74, 0x31, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0f, 0x6d, 0x79, 0x46, 0x69, 0x78, 0x65,
0x64, 0x43, 0x61, 0x70, 0x41, 0x73, 0x73, 0x65,
0x74, 0x00, 0x04, 0x4d, 0x46, 0x43, 0x41, 0x08,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x50,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x3f, 0x78, 0xe5, 0x10, 0xdf, 0x62, 0xbc, 0x48,
0xb0, 0x82, 0x9e, 0xc0, 0x6d, 0x6a, 0x6b, 0x98,
0x06, 0x2d, 0x69, 0x53, 0x00, 0x00, 0x00, 0x06,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x50,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0xc5, 0x49, 0x03, 0xde, 0x51, 0x77, 0xa1, 0x6f,
0x78, 0x11, 0x77, 0x1e, 0xf2, 0xf4, 0x65, 0x9d,
0x9e, 0x86, 0x46, 0x71, 0x00, 0x00, 0x00, 0x06,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x86, 0xa0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x3f, 0x58, 0xfd, 0xa2, 0xe9, 0xea, 0x8d, 0x9e,
0x4b, 0x18, 0x18, 0x32, 0xa0, 0x7b, 0x26, 0xda,
0xe2, 0x86, 0xf2, 0xcb, 0x00, 0x00, 0x00, 0x06,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x86, 0xa0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x64, 0x59, 0x38, 0xbb, 0x7a, 0xe2, 0x19, 0x32,
0x70, 0xe6, 0xff, 0xef, 0x00, 0x9e, 0x36, 0x64,
0xd1, 0x1e, 0x07, 0xc1, 0x00, 0x06, 0x61, 0x73,
0x73, 0x65, 0x74, 0x32, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0d, 0x6d, 0x79, 0x56, 0x61, 0x72, 0x43,
0x61, 0x70, 0x41, 0x73, 0x73, 0x65, 0x74, 0x00,
0x04, 0x4d, 0x56, 0x43, 0x41, 0x00, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x3f, 0x58,
0xfd, 0xa2, 0xe9, 0xea, 0x8d, 0x9e, 0x4b, 0x18,
0x18, 0x32, 0xa0, 0x7b, 0x26, 0xda, 0xe2, 0x86,
0xf2, 0xcb, 0x64, 0x59, 0x38, 0xbb, 0x7a, 0xe2,
0x19, 0x32, 0x70, 0xe6, 0xff, 0xef, 0x00, 0x9e,
0x36, 0x64, 0xd1, 0x1e, 0x07, 0xc1, 0x00, 0x00,
0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x02, 0x3f, 0x78, 0xe5, 0x10, 0xdf, 0x62,
0xbc, 0x48, 0xb0, 0x82, 0x9e, 0xc0, 0x6d, 0x6a,
0x6b, 0x98, 0x06, 0x2d, 0x69, 0x53, 0xc5, 0x49,
0x03, 0xde, 0x51, 0x77, 0xa1, 0x6f, 0x78, 0x11,
0x77, 0x1e, 0xf2, 0xf4, 0x65, 0x9d, 0x9e, 0x86,
0x46, 0x71, 0x00, 0x06, 0x61, 0x73, 0x73, 0x65,
0x74, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
0x6d, 0x79, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x56,
0x61, 0x72, 0x43, 0x61, 0x70, 0x41, 0x73, 0x73,
0x65, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x64, 0x59, 0x38,
0xbb, 0x7a, 0xe2, 0x19, 0x32, 0x70, 0xe6, 0xff,
0xef, 0x00, 0x9e, 0x36, 0x64, 0xd1, 0x1e, 0x07,
0xc1,
}}
if result := reply.Bytes.String(); result != expected.String() {
t.Fatalf("Create genesis returned:\n%s\nExpected:\n%s",
formatting.DumpBytes{Bytes: reply.Bytes.Bytes},
formatting.DumpBytes{Bytes: expected.Bytes},
)
}
}

View File

@ -25,6 +25,7 @@ type UnsignedTx interface {
Bytes() []byte
AssetIDs() ids.Set
NumCredentials() int
InputUTXOs() []*ava.UTXOID
UTXOs() []*ava.UTXO
@ -65,8 +66,7 @@ func (t *Tx) SyntacticVerify(ctx *snow.Context, c codec.Codec, numFxs int) error
}
}
numInputs := len(t.InputUTXOs())
if numInputs != len(t.Creds) {
if numCreds := t.UnsignedTx.NumCredentials(); numCreds != len(t.Creds) {
return errWrongNumberOfCredentials
}
return nil

View File

@ -27,6 +27,13 @@ func TestTxEmpty(t *testing.T) {
c.RegisterType(&BaseTx{})
c.RegisterType(&CreateAssetTx{})
c.RegisterType(&OperationTx{})
c.RegisterType(&ImportTx{})
c.RegisterType(&ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
tx := &Tx{}
if err := tx.SyntacticVerify(ctx, c, 1); err == nil {
@ -39,10 +46,12 @@ func TestTxInvalidCredential(t *testing.T) {
c.RegisterType(&BaseTx{})
c.RegisterType(&CreateAssetTx{})
c.RegisterType(&OperationTx{})
c.RegisterType(&ImportTx{})
c.RegisterType(&ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
c.RegisterType(&ava.TestVerifiable{})
@ -85,10 +94,12 @@ func TestTxInvalidUnsignedTx(t *testing.T) {
c.RegisterType(&BaseTx{})
c.RegisterType(&CreateAssetTx{})
c.RegisterType(&OperationTx{})
c.RegisterType(&ImportTx{})
c.RegisterType(&ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
c.RegisterType(&ava.TestVerifiable{})
@ -151,19 +162,21 @@ func TestTxInvalidNumberOfCredentials(t *testing.T) {
c.RegisterType(&BaseTx{})
c.RegisterType(&CreateAssetTx{})
c.RegisterType(&OperationTx{})
c.RegisterType(&ImportTx{})
c.RegisterType(&ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
c.RegisterType(&ava.TestVerifiable{})
tx := &Tx{
UnsignedTx: &OperationTx{
BaseTx: BaseTx{
NetID: networkID,
BCID: chainID,
Ins: []*ava.TransferableInput{&ava.TransferableInput{
UnsignedTx: &BaseTx{
NetID: networkID,
BCID: chainID,
Ins: []*ava.TransferableInput{
&ava.TransferableInput{
UTXOID: ava.UTXOID{TxID: ids.Empty, OutputIndex: 0},
Asset: ava.Asset{ID: asset},
In: &secp256k1fx.TransferInput{
@ -174,18 +187,16 @@ func TestTxInvalidNumberOfCredentials(t *testing.T) {
},
},
},
}},
},
Ops: []*Operation{
&Operation{
Asset: ava.Asset{ID: asset},
Ins: []*OperableInput{
&OperableInput{
UTXOID: ava.UTXOID{
TxID: ids.Empty,
OutputIndex: 1,
},
&ava.TransferableInput{
UTXOID: ava.UTXOID{TxID: ids.Empty, OutputIndex: 1},
Asset: ava.Asset{ID: asset},
In: &secp256k1fx.TransferInput{
Amt: 20 * units.KiloAva,
Input: secp256k1fx.Input{
SigIndices: []uint32{
0,
},
In: &ava.TestVerifiable{},
},
},
},
@ -204,76 +215,3 @@ func TestTxInvalidNumberOfCredentials(t *testing.T) {
t.Fatalf("Tx should have failed due to an invalid unsigned tx")
}
}
func TestTxDocumentation(t *testing.T) {
c := codec.NewDefault()
c.RegisterType(&BaseTx{})
c.RegisterType(&CreateAssetTx{})
c.RegisterType(&OperationTx{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.Credential{})
txBytes := []byte{
// unsigned transaction:
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0xff, 0xff, 0xff, 0xff, 0xee, 0xee, 0xee, 0xee,
0xdd, 0xdd, 0xdd, 0xdd, 0xcc, 0xcc, 0xcc, 0xcc,
0xbb, 0xbb, 0xbb, 0xbb, 0xaa, 0xaa, 0xaa, 0xaa,
0x99, 0x99, 0x99, 0x99, 0x88, 0x88, 0x88, 0x88,
0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
0x1c, 0x1d, 0x1e, 0x1f, 0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x31,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02,
0x51, 0x02, 0x5c, 0x61, 0xfb, 0xcf, 0xc0, 0x78,
0xf6, 0x93, 0x34, 0xf8, 0x34, 0xbe, 0x6d, 0xd2,
0x6d, 0x55, 0xa9, 0x55, 0xc3, 0x34, 0x41, 0x28,
0xe0, 0x60, 0x12, 0x8e, 0xde, 0x35, 0x23, 0xa2,
0x4a, 0x46, 0x1c, 0x89, 0x43, 0xab, 0x08, 0x59,
0x00, 0x00, 0x00, 0x01, 0xf1, 0xe1, 0xd1, 0xc1,
0xb1, 0xa1, 0x91, 0x81, 0x71, 0x61, 0x51, 0x41,
0x31, 0x21, 0x11, 0x01, 0xf0, 0xe0, 0xd0, 0xc0,
0xb0, 0xa0, 0x90, 0x80, 0x70, 0x60, 0x50, 0x40,
0x30, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x05,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
0x07, 0x5b, 0xcd, 0x15, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07,
// number of credentials:
0x00, 0x00, 0x00, 0x01,
// credential[0]:
0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1e, 0x1d, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2e, 0x2d, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x00, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e,
0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56,
0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5e, 0x5d,
0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6e, 0x6d,
0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e,
0x7f, 0x00,
}
tx := Tx{}
err := c.Unmarshal(txBytes, &tx)
if err != nil {
t.Fatal(err)
}
}

View File

@ -21,6 +21,7 @@ import (
"github.com/ava-labs/gecko/snow/consensus/snowstorm"
"github.com/ava-labs/gecko/snow/engine/common"
"github.com/ava-labs/gecko/utils/formatting"
"github.com/ava-labs/gecko/utils/logging"
"github.com/ava-labs/gecko/utils/timer"
"github.com/ava-labs/gecko/utils/wrappers"
"github.com/ava-labs/gecko/vms/components/ava"
@ -332,6 +333,9 @@ func (vm *VM) Clock() *timer.Clock { return &vm.clock }
// Codec returns a reference to the internal codec of this VM
func (vm *VM) Codec() codec.Codec { return vm.codec }
// Logger returns a reference to the internal logger of this VM
func (vm *VM) Logger() logging.Logger { return vm.ctx.Log }
/*
******************************************************************************
********************************** Timer API *********************************

View File

@ -54,10 +54,10 @@ func GetFirstTxFromGenesisTest(genesisBytes []byte, t *testing.T) *Tx {
c.RegisterType(&OperationTx{})
c.RegisterType(&ImportTx{})
c.RegisterType(&ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
genesis := Genesis{}
@ -192,7 +192,7 @@ func GenesisVM(t *testing.T) *VM {
func TestTxSerialization(t *testing.T) {
expected := []byte{
// txID:
0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x01,
// networkID:
0x00, 0x00, 0xa8, 0x66,
// chainID:
@ -209,7 +209,7 @@ func TestTxSerialization(t *testing.T) {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// fxID:
0x00, 0x00, 0x00, 0x06,
0x00, 0x00, 0x00, 0x07,
// secp256k1 Transferable Output:
// amount:
0x00, 0x00, 0x12, 0x30, 0x9c, 0xe5, 0x40, 0x00,
@ -230,7 +230,7 @@ func TestTxSerialization(t *testing.T) {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// fxID:
0x00, 0x00, 0x00, 0x06,
0x00, 0x00, 0x00, 0x07,
// secp256k1 Transferable Output:
// amount:
0x00, 0x00, 0x12, 0x30, 0x9c, 0xe5, 0x40, 0x00,
@ -251,7 +251,7 @@ func TestTxSerialization(t *testing.T) {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// fxID:
0x00, 0x00, 0x00, 0x06,
0x00, 0x00, 0x00, 0x07,
// secp256k1 Transferable Output:
// amount:
0x00, 0x00, 0x12, 0x30, 0x9c, 0xe5, 0x40, 0x00,
@ -267,20 +267,24 @@ func TestTxSerialization(t *testing.T) {
0x92, 0xf0, 0xee, 0x31,
// number of inputs:
0x00, 0x00, 0x00, 0x00,
// number of operations:
// name length:
0x00, 0x04,
// name:
'n', 'a', 'm', 'e',
// symbol length:
0x00, 0x04,
// symbol:
's', 'y', 'm', 'b',
// denomination
0x00,
// number of initial states:
0x00, 0x00, 0x00, 0x01,
// operation[0]:
// assetID:
0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// number of inputs:
// fx index:
0x00, 0x00, 0x00, 0x00,
// number of outputs:
0x00, 0x00, 0x00, 0x01,
// fxID:
0x00, 0x00, 0x00, 0x05,
0x00, 0x00, 0x00, 0x06,
// secp256k1 Mint Output:
// threshold:
0x00, 0x00, 0x00, 0x01,
@ -294,14 +298,17 @@ func TestTxSerialization(t *testing.T) {
0x00, 0x00, 0x00, 0x00,
}
unsignedTx := &OperationTx{
unsignedTx := &CreateAssetTx{
BaseTx: BaseTx{
NetID: networkID,
BCID: chainID,
},
Ops: []*Operation{
&Operation{
Asset: ava.Asset{ID: asset},
Name: "name",
Symbol: "symb",
Denomination: 0,
States: []*InitialState{
&InitialState{
FxID: 0,
Outs: []verify.Verifiable{
&secp256k1fx.MintOutput{
OutputOwners: secp256k1fx.OutputOwners{
@ -335,10 +342,10 @@ func TestTxSerialization(t *testing.T) {
c.RegisterType(&OperationTx{})
c.RegisterType(&ImportTx{})
c.RegisterType(&ExportTx{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOutput{})
c.RegisterType(&secp256k1fx.TransferOutput{})
c.RegisterType(&secp256k1fx.MintInput{})
c.RegisterType(&secp256k1fx.TransferInput{})
c.RegisterType(&secp256k1fx.MintOperation{})
c.RegisterType(&secp256k1fx.Credential{})
b, err := c.Marshal(tx)

View File

@ -4,9 +4,12 @@
package ava
import (
"bytes"
"errors"
"sort"
"github.com/ava-labs/gecko/ids"
"github.com/ava-labs/gecko/utils"
)
var (
@ -52,3 +55,29 @@ func (utxo *UTXOID) Verify() error {
return nil
}
}
type innerSortUTXOIDs []*UTXOID
func (utxos innerSortUTXOIDs) Less(i, j int) bool {
iID, iIndex := utxos[i].InputSource()
jID, jIndex := utxos[j].InputSource()
switch bytes.Compare(iID.Bytes(), jID.Bytes()) {
case -1:
return true
case 0:
return iIndex < jIndex
default:
return false
}
}
func (utxos innerSortUTXOIDs) Len() int { return len(utxos) }
func (utxos innerSortUTXOIDs) Swap(i, j int) { utxos[j], utxos[i] = utxos[i], utxos[j] }
// SortUTXOIDs ...
func SortUTXOIDs(utxos []*UTXOID) { sort.Sort(innerSortUTXOIDs(utxos)) }
// IsSortedAndUniqueUTXOIDs ...
func IsSortedAndUniqueUTXOIDs(utxos []*UTXOID) bool {
return utils.IsSortedAndUnique(innerSortUTXOIDs(utxos))
}

View File

@ -194,7 +194,7 @@ func (tx *ImportTx) SemanticVerify(db database.Database) error {
return errAssetIDMismatch
}
if err := tx.vm.fx.VerifyTransfer(tx, utxo.Out, in.In, cred); err != nil {
if err := tx.vm.fx.VerifyTransfer(tx, in.In, cred, utxo.Out); err != nil {
return err
}
}

View File

@ -20,6 +20,7 @@ import (
"github.com/ava-labs/gecko/snow/engine/common"
"github.com/ava-labs/gecko/snow/validators"
"github.com/ava-labs/gecko/utils/crypto"
"github.com/ava-labs/gecko/utils/logging"
"github.com/ava-labs/gecko/utils/math"
"github.com/ava-labs/gecko/utils/timer"
"github.com/ava-labs/gecko/utils/units"
@ -112,10 +113,10 @@ func init() {
Codec.RegisterType(&StandardBlock{}),
Codec.RegisterType(&AtomicBlock{}),
Codec.RegisterType(&secp256k1fx.TransferInput{}),
Codec.RegisterType(&secp256k1fx.MintOutput{}),
Codec.RegisterType(&secp256k1fx.TransferOutput{}),
Codec.RegisterType(&secp256k1fx.MintInput{}),
Codec.RegisterType(&secp256k1fx.TransferInput{}),
Codec.RegisterType(&secp256k1fx.MintOperation{}),
Codec.RegisterType(&secp256k1fx.Credential{}),
Codec.RegisterType(&UnsignedAddDefaultSubnetValidatorTx{}),
@ -742,6 +743,9 @@ func (vm *VM) Codec() codec.Codec { return vm.codec }
// Clock ...
func (vm *VM) Clock() *timer.Clock { return &vm.clock }
// Logger ...
func (vm *VM) Logger() logging.Logger { return vm.Ctx.Log }
// GetAtomicUTXOs returns the utxos that at least one of the provided addresses is
// referenced in.
func (vm *VM) GetAtomicUTXOs(addrs ids.Set) ([]*ava.UTXO, error) {

View File

@ -0,0 +1,15 @@
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package secp256k1fx
import (
"testing"
)
func TestFactory(t *testing.T) {
factory := Factory{}
if fx := factory.New(); fx == nil {
t.Fatalf("Factory.New returned nil")
}
}

View File

@ -8,23 +8,22 @@ import (
"github.com/ava-labs/gecko/utils/crypto"
"github.com/ava-labs/gecko/utils/hashing"
"github.com/ava-labs/gecko/utils/wrappers"
"github.com/ava-labs/gecko/vms/components/verify"
)
var (
errWrongVMType = errors.New("wrong vm type")
errWrongTxType = errors.New("wrong tx type")
errWrongOpType = errors.New("wrong operation type")
errWrongUTXOType = errors.New("wrong utxo type")
errWrongOutputType = errors.New("wrong output type")
errWrongInputType = errors.New("wrong input type")
errWrongCredentialType = errors.New("wrong credential type")
errWrongNumberOfOutputs = errors.New("wrong number of outputs for an operation")
errWrongNumberOfInputs = errors.New("wrong number of inputs for an operation")
errWrongNumberOfCredentials = errors.New("wrong number of credentials for an operation")
errWrongMintCreated = errors.New("wrong mint output created from the operation")
errWrongNumberOfUTXOs = errors.New("wrong number of utxos for the operation")
errWrongMintCreated = errors.New("wrong mint output created from the operation")
errWrongAmounts = errors.New("input is consuming a different amount than expected")
errTimelocked = errors.New("output is time locked")
errTooManySigners = errors.New("input has more signers than expected")
@ -33,93 +32,85 @@ var (
errWrongSigner = errors.New("credential does not produce expected signer")
)
// Fx ...
// Fx describes the secp256k1 feature extension
type Fx struct {
vm VM
secpFactory crypto.FactorySECP256K1R
VM VM
SECPFactory crypto.FactorySECP256K1R
}
// Initialize ...
func (fx *Fx) Initialize(vmIntf interface{}) error {
if err := fx.InitializeVM(vmIntf); err != nil {
return err
}
log := fx.VM.Logger()
log.Debug("Initializing secp561k1 fx")
c := fx.VM.Codec()
errs := wrappers.Errs{}
errs.Add(
c.RegisterType(&TransferInput{}),
c.RegisterType(&MintOutput{}),
c.RegisterType(&TransferOutput{}),
c.RegisterType(&MintOperation{}),
c.RegisterType(&Credential{}),
)
return errs.Err
}
// InitializeVM ...
func (fx *Fx) InitializeVM(vmIntf interface{}) error {
vm, ok := vmIntf.(VM)
if !ok {
return errWrongVMType
}
c := vm.Codec()
c.RegisterType(&MintOutput{})
c.RegisterType(&TransferOutput{})
c.RegisterType(&MintInput{})
c.RegisterType(&TransferInput{})
c.RegisterType(&Credential{})
fx.vm = vm
fx.VM = vm
return nil
}
// VerifyOperation ...
func (fx *Fx) VerifyOperation(txIntf interface{}, utxosIntf, insIntf, credsIntf, outsIntf []interface{}) error {
func (fx *Fx) VerifyOperation(txIntf, opIntf, credIntf interface{}, utxosIntf []interface{}) error {
tx, ok := txIntf.(Tx)
if !ok {
return errWrongTxType
}
if len(outsIntf) != 2 {
return errWrongNumberOfOutputs
}
if len(utxosIntf) != 1 || len(insIntf) != 1 {
return errWrongNumberOfInputs
}
if len(credsIntf) != 1 {
return errWrongNumberOfCredentials
}
utxo, ok := utxosIntf[0].(*MintOutput)
op, ok := opIntf.(*MintOperation)
if !ok {
return errWrongUTXOType
return errWrongOpType
}
in, ok := insIntf[0].(*MintInput)
if !ok {
return errWrongInputType
}
cred, ok := credsIntf[0].(*Credential)
cred, ok := credIntf.(*Credential)
if !ok {
return errWrongCredentialType
}
newMint, ok := outsIntf[0].(*MintOutput)
if !ok {
return errWrongOutputType
if len(utxosIntf) != 1 {
return errWrongNumberOfUTXOs
}
newOutput, ok := outsIntf[1].(*TransferOutput)
out, ok := utxosIntf[0].(*MintOutput)
if !ok {
return errWrongOutputType
return errWrongUTXOType
}
return fx.verifyOperation(tx, utxo, in, cred, newMint, newOutput)
return fx.verifyOperation(tx, op, cred, out)
}
func (fx *Fx) verifyOperation(tx Tx, utxo *MintOutput, in *MintInput, cred *Credential, newMint *MintOutput, newOutput *TransferOutput) error {
if err := verify.All(utxo, in, cred, newMint, newOutput); err != nil {
func (fx *Fx) verifyOperation(tx Tx, op *MintOperation, cred *Credential, utxo *MintOutput) error {
if err := verify.All(op, cred, utxo); err != nil {
return err
}
if !utxo.Equals(&newMint.OutputOwners) {
if !utxo.Equals(&op.MintOutput.OutputOwners) {
return errWrongMintCreated
}
return fx.verifyCredentials(tx, &utxo.OutputOwners, &in.Input, cred)
return fx.VerifyCredentials(tx, &op.MintInput, cred, &utxo.OutputOwners)
}
// VerifyTransfer ...
func (fx *Fx) VerifyTransfer(txIntf, utxoIntf, inIntf, credIntf interface{}) error {
func (fx *Fx) VerifyTransfer(txIntf, inIntf, credIntf, utxoIntf interface{}) error {
tx, ok := txIntf.(Tx)
if !ok {
return errWrongTxType
}
utxo, ok := utxoIntf.(*TransferOutput)
if !ok {
return errWrongUTXOType
}
in, ok := inIntf.(*TransferInput)
if !ok {
return errWrongInputType
@ -128,15 +119,20 @@ func (fx *Fx) VerifyTransfer(txIntf, utxoIntf, inIntf, credIntf interface{}) err
if !ok {
return errWrongCredentialType
}
return fx.verifyTransfer(tx, utxo, in, cred)
out, ok := utxoIntf.(*TransferOutput)
if !ok {
return errWrongUTXOType
}
return fx.VerifySpend(tx, in, cred, out)
}
func (fx *Fx) verifyTransfer(tx Tx, utxo *TransferOutput, in *TransferInput, cred *Credential) error {
// VerifySpend ensures that the utxo can be sent to any address
func (fx *Fx) VerifySpend(tx Tx, in *TransferInput, cred *Credential, utxo *TransferOutput) error {
if err := verify.All(utxo, in, cred); err != nil {
return err
}
clock := fx.vm.Clock()
clock := fx.VM.Clock()
switch {
case utxo.Amt != in.Amt:
return errWrongAmounts
@ -144,10 +140,12 @@ func (fx *Fx) verifyTransfer(tx Tx, utxo *TransferOutput, in *TransferInput, cre
return errTimelocked
}
return fx.verifyCredentials(tx, &utxo.OutputOwners, &in.Input, cred)
return fx.VerifyCredentials(tx, &in.Input, cred, &utxo.OutputOwners)
}
func (fx *Fx) verifyCredentials(tx Tx, out *OutputOwners, in *Input, cred *Credential) error {
// VerifyCredentials ensures that the output can be spent by the input with the
// credential. A nil return values means the output can be spent.
func (fx *Fx) VerifyCredentials(tx Tx, in *Input, cred *Credential, out *OutputOwners) error {
numSigs := len(in.SigIndices)
switch {
case out.Threshold < uint32(numSigs):
@ -164,7 +162,7 @@ func (fx *Fx) verifyCredentials(tx Tx, out *OutputOwners, in *Input, cred *Crede
for i, index := range in.SigIndices {
sig := cred.Sigs[i]
pk, err := fx.secpFactory.RecoverHashPublicKey(txHash, sig[:])
pk, err := fx.SECPFactory.RecoverHashPublicKey(txHash, sig[:])
if err != nil {
return err
}

View File

@ -10,6 +10,7 @@ import (
"github.com/ava-labs/gecko/ids"
"github.com/ava-labs/gecko/utils/crypto"
"github.com/ava-labs/gecko/utils/hashing"
"github.com/ava-labs/gecko/utils/logging"
"github.com/ava-labs/gecko/utils/timer"
"github.com/ava-labs/gecko/vms/components/codec"
)
@ -40,6 +41,8 @@ func (vm *testVM) Codec() codec.Codec { return codec.NewDefault() }
func (vm *testVM) Clock() *timer.Clock { return &vm.clock }
func (vm *testVM) Logger() logging.Logger { return logging.NoLog{} }
type testCodec struct{}
func (c *testCodec) RegisterStruct(interface{}) {}
@ -98,8 +101,7 @@ func TestFxVerifyTransfer(t *testing.T) {
},
}
err := fx.VerifyTransfer(tx, out, in, cred)
if err != nil {
if err := fx.VerifyTransfer(tx, in, cred, out); err != nil {
t.Fatal(err)
}
}
@ -134,8 +136,7 @@ func TestFxVerifyTransferNilTx(t *testing.T) {
},
}
err := fx.VerifyTransfer(nil, out, in, cred)
if err == nil {
if err := fx.VerifyTransfer(nil, in, cred, out); err == nil {
t.Fatalf("Should have failed verification due to a nil tx")
}
}
@ -163,8 +164,7 @@ func TestFxVerifyTransferNilOutput(t *testing.T) {
},
}
err := fx.VerifyTransfer(tx, nil, in, cred)
if err == nil {
if err := fx.VerifyTransfer(tx, in, cred, nil); err == nil {
t.Fatalf("Should have failed verification due to a nil output")
}
}
@ -196,8 +196,7 @@ func TestFxVerifyTransferNilInput(t *testing.T) {
},
}
err := fx.VerifyTransfer(tx, out, nil, cred)
if err == nil {
if err := fx.VerifyTransfer(tx, nil, cred, out); err == nil {
t.Fatalf("Should have failed verification due to a nil input")
}
}
@ -230,8 +229,7 @@ func TestFxVerifyTransferNilCredential(t *testing.T) {
},
}
err := fx.VerifyTransfer(tx, out, in, nil)
if err == nil {
if err := fx.VerifyTransfer(tx, in, nil, out); err == nil {
t.Fatalf("Should have failed verification due to a nil credential")
}
}
@ -269,8 +267,7 @@ func TestFxVerifyTransferInvalidOutput(t *testing.T) {
},
}
err := fx.VerifyTransfer(tx, out, in, cred)
if err == nil {
if err := fx.VerifyTransfer(tx, in, cred, out); err == nil {
t.Fatalf("Should have errored due to an invalid output")
}
}
@ -308,8 +305,7 @@ func TestFxVerifyTransferWrongAmounts(t *testing.T) {
},
}
err := fx.VerifyTransfer(tx, out, in, cred)
if err == nil {
if err := fx.VerifyTransfer(tx, in, cred, out); err == nil {
t.Fatalf("Should have errored due to different amounts")
}
}
@ -347,8 +343,7 @@ func TestFxVerifyTransferTimelocked(t *testing.T) {
},
}
err := fx.VerifyTransfer(tx, out, in, cred)
if err == nil {
if err := fx.VerifyTransfer(tx, in, cred, out); err == nil {
t.Fatalf("Should have errored due to a timelocked output")
}
}
@ -387,8 +382,7 @@ func TestFxVerifyTransferTooManySigners(t *testing.T) {
},
}
err := fx.VerifyTransfer(tx, out, in, cred)
if err == nil {
if err := fx.VerifyTransfer(tx, in, cred, out); err == nil {
t.Fatalf("Should have errored due to too many signers")
}
}
@ -424,8 +418,7 @@ func TestFxVerifyTransferTooFewSigners(t *testing.T) {
Sigs: [][crypto.SECP256K1RSigLen]byte{},
}
err := fx.VerifyTransfer(tx, out, in, cred)
if err == nil {
if err := fx.VerifyTransfer(tx, in, cred, out); err == nil {
t.Fatalf("Should have errored due to too few signers")
}
}
@ -464,8 +457,7 @@ func TestFxVerifyTransferMismatchedSigners(t *testing.T) {
},
}
err := fx.VerifyTransfer(tx, out, in, cred)
if err == nil {
if err := fx.VerifyTransfer(tx, in, cred, out); err == nil {
t.Fatalf("Should have errored due to too mismatched signers")
}
}
@ -503,8 +495,7 @@ func TestFxVerifyTransferInvalidSignature(t *testing.T) {
},
}
err := fx.VerifyTransfer(tx, out, in, cred)
if err == nil {
if err := fx.VerifyTransfer(tx, in, cred, out); err == nil {
t.Fatalf("Should have errored due to an invalid signature")
}
}
@ -542,8 +533,7 @@ func TestFxVerifyTransferWrongSigner(t *testing.T) {
},
}
err := fx.VerifyTransfer(tx, out, in, cred)
if err == nil {
if err := fx.VerifyTransfer(tx, in, cred, out); err == nil {
t.Fatalf("Should have errored due to a wrong signer")
}
}
@ -567,40 +557,37 @@ func TestFxVerifyOperation(t *testing.T) {
},
},
}
in := &MintInput{
Input: Input{
op := &MintOperation{
MintInput: Input{
SigIndices: []uint32{0},
},
MintOutput: MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
},
TransferOutput: TransferOutput{
Amt: 1,
Locktime: 0,
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
},
}
cred := &Credential{
Sigs: [][crypto.SECP256K1RSigLen]byte{
sigBytes,
},
}
mintOutput := &MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
}
transferOutput := &TransferOutput{
Amt: 1,
Locktime: 0,
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
}
utxos := []interface{}{utxo}
ins := []interface{}{in}
creds := []interface{}{cred}
outs := []interface{}{mintOutput, transferOutput}
err := fx.VerifyOperation(tx, utxos, ins, creds, outs)
err := fx.VerifyOperation(tx, op, cred, utxos)
if err != nil {
t.Fatal(err)
}
@ -622,94 +609,43 @@ func TestFxVerifyOperationUnknownTx(t *testing.T) {
},
},
}
in := &MintInput{
Input: Input{
op := &MintOperation{
MintInput: Input{
SigIndices: []uint32{0},
},
MintOutput: MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
},
TransferOutput: TransferOutput{
Amt: 1,
Locktime: 0,
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
},
}
cred := &Credential{
Sigs: [][crypto.SECP256K1RSigLen]byte{
sigBytes,
},
}
mintOutput := &MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
}
transferOutput := &TransferOutput{
Amt: 1,
Locktime: 0,
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
}
utxos := []interface{}{utxo}
ins := []interface{}{in}
creds := []interface{}{cred}
outs := []interface{}{mintOutput, transferOutput}
err := fx.VerifyOperation(nil, utxos, ins, creds, outs)
err := fx.VerifyOperation(nil, op, cred, utxos)
if err == nil {
t.Fatalf("Should have errored due to an invalid tx type")
}
}
func TestFxVerifyOperationWrongNumberOfOutputs(t *testing.T) {
vm := testVM{}
date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC)
vm.clock.Set(date)
fx := Fx{}
if err := fx.Initialize(&vm); err != nil {
t.Fatal(err)
}
tx := &testTx{
bytes: txBytes,
}
utxo := &MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
}
in := &MintInput{
Input: Input{
SigIndices: []uint32{0},
},
}
cred := &Credential{
Sigs: [][crypto.SECP256K1RSigLen]byte{
sigBytes,
},
}
mintOutput := &MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
}
utxos := []interface{}{utxo}
ins := []interface{}{in}
creds := []interface{}{cred}
outs := []interface{}{mintOutput}
err := fx.VerifyOperation(tx, utxos, ins, creds, outs)
if err == nil {
t.Fatalf("Should have errored due to a wrong number of outputs")
}
}
func TestFxVerifyOperationWrongNumberOfInputs(t *testing.T) {
func TestFxVerifyOperationUnknownOperation(t *testing.T) {
vm := testVM{}
date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC)
vm.clock.Set(date)
@ -733,35 +669,15 @@ func TestFxVerifyOperationWrongNumberOfInputs(t *testing.T) {
sigBytes,
},
}
mintOutput := &MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
}
transferOutput := &TransferOutput{
Amt: 1,
Locktime: 0,
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
}
utxos := []interface{}{utxo}
creds := []interface{}{cred}
outs := []interface{}{mintOutput, transferOutput}
err := fx.VerifyOperation(tx, utxos, nil, creds, outs)
err := fx.VerifyOperation(tx, nil, cred, utxos)
if err == nil {
t.Fatalf("Should have errored due to a wrong number of inputs")
t.Fatalf("Should have errored due to an invalid operation type")
}
}
func TestFxVerifyOperationWrongNumberOfCredentials(t *testing.T) {
func TestFxVerifyOperationUnknownCredential(t *testing.T) {
vm := testVM{}
date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC)
vm.clock.Set(date)
@ -780,40 +696,38 @@ func TestFxVerifyOperationWrongNumberOfCredentials(t *testing.T) {
},
},
}
in := &MintInput{
Input: Input{
op := &MintOperation{
MintInput: Input{
SigIndices: []uint32{0},
},
}
mintOutput := &MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
MintOutput: MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
},
}
transferOutput := &TransferOutput{
Amt: 1,
Locktime: 0,
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
TransferOutput: TransferOutput{
Amt: 1,
Locktime: 0,
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
},
}
utxos := []interface{}{utxo}
ins := []interface{}{in}
outs := []interface{}{mintOutput, transferOutput}
err := fx.VerifyOperation(tx, utxos, ins, nil, outs)
err := fx.VerifyOperation(tx, op, nil, utxos)
if err == nil {
t.Fatalf("Should have errored due to a wrong number of credentials")
t.Fatalf("Should have errored due to an invalid credential type")
}
}
func TestFxVerifyOperationWrongUTXOType(t *testing.T) {
func TestFxVerifyOperationWrongNumberOfUTXOs(t *testing.T) {
vm := testVM{}
date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC)
vm.clock.Set(date)
@ -824,9 +738,7 @@ func TestFxVerifyOperationWrongUTXOType(t *testing.T) {
tx := &testTx{
bytes: txBytes,
}
utxo := &TransferOutput{
Amt: 1,
Locktime: 0,
utxo := &MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
@ -834,46 +746,43 @@ func TestFxVerifyOperationWrongUTXOType(t *testing.T) {
},
},
}
in := &MintInput{
Input: Input{
op := &MintOperation{
MintInput: Input{
SigIndices: []uint32{0},
},
MintOutput: MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
},
TransferOutput: TransferOutput{
Amt: 1,
Locktime: 0,
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
},
}
cred := &Credential{
Sigs: [][crypto.SECP256K1RSigLen]byte{
sigBytes,
},
}
mintOutput := &MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
}
transferOutput := &TransferOutput{
Amt: 1,
Locktime: 0,
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
}
utxos := []interface{}{utxo}
ins := []interface{}{in}
creds := []interface{}{cred}
outs := []interface{}{mintOutput, transferOutput}
err := fx.VerifyOperation(tx, utxos, ins, creds, outs)
utxos := []interface{}{utxo, utxo}
err := fx.VerifyOperation(tx, op, cred, utxos)
if err == nil {
t.Fatalf("Should have errored due to a wrong utxo type")
t.Fatalf("Should have errored due to a wrong number of utxos")
}
}
func TestFxVerifyOperationWrongInputType(t *testing.T) {
func TestFxVerifyOperationUnknownUTXOType(t *testing.T) {
vm := testVM{}
date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC)
vm.clock.Set(date)
@ -884,18 +793,27 @@ func TestFxVerifyOperationWrongInputType(t *testing.T) {
tx := &testTx{
bytes: txBytes,
}
utxo := &MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
op := &MintOperation{
MintInput: Input{
SigIndices: []uint32{0},
},
MintOutput: MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
},
}
in := &TransferInput{
Amt: 1,
Input: Input{
SigIndices: []uint32{0},
TransferOutput: TransferOutput{
Amt: 1,
Locktime: 0,
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
},
}
cred := &Credential{
@ -903,36 +821,15 @@ func TestFxVerifyOperationWrongInputType(t *testing.T) {
sigBytes,
},
}
mintOutput := &MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
}
transferOutput := &TransferOutput{
Amt: 1,
Locktime: 0,
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
}
utxos := []interface{}{utxo}
ins := []interface{}{in}
creds := []interface{}{cred}
outs := []interface{}{mintOutput, transferOutput}
err := fx.VerifyOperation(tx, utxos, ins, creds, outs)
utxos := []interface{}{nil}
err := fx.VerifyOperation(tx, op, cred, utxos)
if err == nil {
t.Fatalf("Should have errored due to a wrong input type")
t.Fatalf("Should have errored due to an invalid utxo type")
}
}
func TestFxVerifyOperationWrongCredentialType(t *testing.T) {
func TestFxVerifyOperationInvalidOperationVerify(t *testing.T) {
vm := testVM{}
date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC)
vm.clock.Set(date)
@ -951,101 +848,40 @@ func TestFxVerifyOperationWrongCredentialType(t *testing.T) {
},
},
}
in := &MintInput{
Input: Input{
op := &MintOperation{
MintInput: Input{
SigIndices: []uint32{0},
},
}
mintOutput := &MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
MintOutput: MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
},
}
transferOutput := &TransferOutput{
Amt: 1,
Locktime: 0,
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
TransferOutput: TransferOutput{
Amt: 1,
Locktime: 0,
OutputOwners: OutputOwners{
Threshold: 1,
},
},
}
utxos := []interface{}{utxo}
ins := []interface{}{in}
creds := []interface{}{nil}
outs := []interface{}{mintOutput, transferOutput}
err := fx.VerifyOperation(tx, utxos, ins, creds, outs)
if err == nil {
t.Fatalf("Should have errored due to a wrong credential type")
}
}
func TestFxVerifyOperationWrongMintType(t *testing.T) {
vm := testVM{}
date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC)
vm.clock.Set(date)
fx := Fx{}
if err := fx.Initialize(&vm); err != nil {
t.Fatal(err)
}
tx := &testTx{
bytes: txBytes,
}
utxo := &MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
}
in := &MintInput{
Input: Input{
SigIndices: []uint32{0},
},
}
cred := &Credential{
Sigs: [][crypto.SECP256K1RSigLen]byte{
sigBytes,
},
}
mintOutput := &TransferOutput{
Amt: 1,
Locktime: 0,
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
}
transferOutput := &TransferOutput{
Amt: 1,
Locktime: 0,
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
}
utxos := []interface{}{utxo}
ins := []interface{}{in}
creds := []interface{}{cred}
outs := []interface{}{mintOutput, transferOutput}
err := fx.VerifyOperation(tx, utxos, ins, creds, outs)
err := fx.VerifyOperation(tx, op, cred, utxos)
if err == nil {
t.Fatalf("Should have errored due to a wrong output type")
t.Fatalf("Should have errored due to a failed verify")
}
}
func TestFxVerifyOperationWrongTransferType(t *testing.T) {
func TestFxVerifyOperationMismatchedMintOutputs(t *testing.T) {
vm := testVM{}
date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC)
vm.clock.Set(date)
@ -1064,152 +900,33 @@ func TestFxVerifyOperationWrongTransferType(t *testing.T) {
},
},
}
in := &MintInput{
Input: Input{
op := &MintOperation{
MintInput: Input{
SigIndices: []uint32{0},
},
MintOutput: MintOutput{
OutputOwners: OutputOwners{},
},
TransferOutput: TransferOutput{
Amt: 1,
Locktime: 0,
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
},
}
cred := &Credential{
Sigs: [][crypto.SECP256K1RSigLen]byte{
sigBytes,
},
}
mintOutput := &MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
}
transferOutput := &MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
}
utxos := []interface{}{utxo}
ins := []interface{}{in}
creds := []interface{}{cred}
outs := []interface{}{mintOutput, transferOutput}
err := fx.VerifyOperation(tx, utxos, ins, creds, outs)
err := fx.VerifyOperation(tx, op, cred, utxos)
if err == nil {
t.Fatalf("Should have errored due to a wrong output type")
}
}
func TestFxVerifyOperationInvalid(t *testing.T) {
vm := testVM{}
date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC)
vm.clock.Set(date)
fx := Fx{}
if err := fx.Initialize(&vm); err != nil {
t.Fatal(err)
}
tx := &testTx{
bytes: txBytes,
}
utxo := &MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
}
in := &MintInput{
Input: Input{
SigIndices: []uint32{0},
},
}
cred := &Credential{
Sigs: [][crypto.SECP256K1RSigLen]byte{
sigBytes,
},
}
mintOutput := &MintOutput{
OutputOwners: OutputOwners{
Threshold: 0,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
}
transferOutput := &TransferOutput{
Amt: 1,
Locktime: 0,
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
}
utxos := []interface{}{utxo}
ins := []interface{}{in}
creds := []interface{}{cred}
outs := []interface{}{mintOutput, transferOutput}
err := fx.VerifyOperation(tx, utxos, ins, creds, outs)
if err == nil {
t.Fatalf("Should have errored due to an invalid output")
}
}
func TestFxVerifyOperationMismatchedMintOutput(t *testing.T) {
vm := testVM{}
date := time.Date(2019, time.January, 19, 16, 25, 17, 3, time.UTC)
vm.clock.Set(date)
fx := Fx{}
if err := fx.Initialize(&vm); err != nil {
t.Fatal(err)
}
tx := &testTx{
bytes: txBytes,
}
utxo := &MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
}
in := &MintInput{
Input: Input{
SigIndices: []uint32{0},
},
}
cred := &Credential{
Sigs: [][crypto.SECP256K1RSigLen]byte{
sigBytes,
},
}
mintOutput := &MintOutput{
OutputOwners: OutputOwners{
Addrs: []ids.ShortID{},
},
}
transferOutput := &TransferOutput{
Amt: 1,
Locktime: 0,
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
}
utxos := []interface{}{utxo}
ins := []interface{}{in}
creds := []interface{}{cred}
outs := []interface{}{mintOutput, transferOutput}
err := fx.VerifyOperation(tx, utxos, ins, creds, outs)
if err == nil {
t.Fatalf("Should have errored due to a mismatched mint output")
t.Fatalf("Should have errored due to the wrong MintOutput being created")
}
}

View File

@ -0,0 +1,36 @@
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package secp256k1fx
import (
"errors"
"github.com/ava-labs/gecko/vms/components/verify"
)
var (
errNilMintOperation = errors.New("nil mint operation")
)
// MintOperation ...
type MintOperation struct {
MintInput Input `serialize:"true"`
MintOutput MintOutput `serialize:"true"`
TransferOutput TransferOutput `serialize:"true"`
}
// Outs ...
func (op *MintOperation) Outs() []verify.Verifiable {
return []verify.Verifiable{&op.MintOutput, &op.TransferOutput}
}
// Verify ...
func (op *MintOperation) Verify() error {
switch {
case op == nil:
return errNilMintOperation
default:
return verify.All(&op.MintInput, &op.MintOutput, &op.TransferOutput)
}
}

View File

@ -0,0 +1,45 @@
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package secp256k1fx
import (
"testing"
"github.com/ava-labs/gecko/ids"
)
func TestMintOperationVerifyNil(t *testing.T) {
op := (*MintOperation)(nil)
if err := op.Verify(); err == nil {
t.Fatalf("MintOperation.Verify should have returned an error due to an nil operation")
}
}
func TestMintOperationOuts(t *testing.T) {
op := &MintOperation{
MintInput: Input{
SigIndices: []uint32{0},
},
MintOutput: MintOutput{
OutputOwners: OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{
ids.NewShortID(addrBytes),
},
},
},
TransferOutput: TransferOutput{
Amt: 1,
Locktime: 0,
OutputOwners: OutputOwners{
Threshold: 1,
},
},
}
outs := op.Outs()
if len(outs) != 2 {
t.Fatalf("Wrong number of outputs")
}
}

View File

@ -4,6 +4,7 @@
package secp256k1fx
import (
"github.com/ava-labs/gecko/utils/logging"
"github.com/ava-labs/gecko/utils/timer"
"github.com/ava-labs/gecko/vms/components/codec"
)
@ -12,4 +13,5 @@ import (
type VM interface {
Codec() codec.Codec
Clock() *timer.Clock
Logger() logging.Logger
}

View File

@ -52,10 +52,10 @@ func NewWallet(log logging.Logger, networkID uint32, chainID ids.ID, txFee uint6
c.RegisterType(&avm.OperationTx{}),
c.RegisterType(&avm.ImportTx{}),
c.RegisterType(&avm.ExportTx{}),
c.RegisterType(&secp256k1fx.TransferInput{}),
c.RegisterType(&secp256k1fx.MintOutput{}),
c.RegisterType(&secp256k1fx.TransferOutput{}),
c.RegisterType(&secp256k1fx.MintInput{}),
c.RegisterType(&secp256k1fx.TransferInput{}),
c.RegisterType(&secp256k1fx.MintOperation{}),
c.RegisterType(&secp256k1fx.Credential{}),
)
return &Wallet{