以下内容为作者本人吐血总结,如有错误、或有问题欢迎请留言讨论,谢谢!
交易前提
- 瑞博币的单位为:1000000
- 发送金额不能小于0.01,否则会返回本地签名认证失败。
- 新的瑞波币地址必须转入20个Xrp才可以激活账户。
- 交易后地址余额必须大于20,否则交易无法被确认,会被节点直接打回。
交易特点
- 瑞波币交易数据采用TV格式(tag、value)
- 编号来源,和定义规则如下
- Tag的计算是由类型以及领域对应的编码计算得到的。
#define XRP_FIELD_TYPE_INT16 @"1"
#define XRP_FIELD_TYPE_INT32 @"2"
#define XRP_FIELD_TYPE_AMOUNT @"6"
#define XRP_FIELD_TYPE_VL @"7"
#define XRP_FIELD_TYPE_ACCOUNT @"8"
交易数据中的每一个参数在对应的领域中都有自己的编码,当前是在交易领域
普通瑞博币转账交易参数编码如下:
@"account": @{@"type": XRP_FIELD_TYPE_ACCOUNT, @"key": @(1)},
@"type": @{@"type": XRP_FIELD_TYPE_INT16, @"key": @(2)},
@"flags": @{@"type": XRP_FIELD_TYPE_INT32, @"key": @(2)},
@"sequence": @{@"type": XRP_FIELD_TYPE_INT32, @"key": @(4)},
@"amount": @{@"type": XRP_FIELD_TYPE_AMOUNT, @"key": @(1)},
@"fee": @{@"type": XRP_FIELD_TYPE_AMOUNT, @"key": @(8)},
@"signingPubKey": @{@"type": XRP_FIELD_TYPE_VL, @"key": @(3)},
@"txnSignature": @{@"type": XRP_FIELD_TYPE_VL, @"key": @(4)},
@"destination": @{@"type": XRP_FIELD_TYPE_ACCOUNT, @"key": @(3)},
@"lastLedgerSequence": @{@"type": XRP_FIELD_TYPE_INT32, @"key": @(27)}
OC代码计算Tag的方式如下
- (void)write_typeWithTransactionData:(NSMutableData *)transaction sourceDicr:(NSDictionary *)sourceDicr
{
if ([sourceDicr[@"key"] intValue] <= 0xf) {
int mark = ([sourceDicr[@"type"] intValue] << 4) | [sourceDicr[@"key"] intValue];
[transaction appendInt8:mark];
}else{
[transaction appendInt8:[sourceDicr[@"type"] intValue] << 4];
[transaction appendInt8:[sourceDicr[@"key"] intValue]];
}
}
重点参数含义
LastLedgerSequence,它是所有事务的可选参数。
- 因为部分情况下,手续费给的过低,可能很久很久没有被确认,又无任何消息响应,如果这笔交易添加了该参数,那么到一定的区块高度时,如果交易还没有被确认,那么交易会被撤回,用户可以重新发送自己当前的金额。
- LastLedgerSequence代表瑞波币区块链一共处理了多少笔交易,我们传入构建交易的这个参数必须要大于这个最新的交易值,如果大于1000,那么在最新的1000笔交易之内必须要完成这笔交易,如果这笔交易在1000之内没有被确认,那么直接按失败处理。不会让用户等过久。
交易详情
交易场景:
交易类型:Payment
发起地址 = rfXSBUpv9Yr41q5qFGRo9LJi1Jbe1wNEFe
接收地址 = rHXKdQhjXUtotW3yaofmu3YyuSZ2FXfxFC
手续费 = 0.01
转账金额 = 0.01
备注 = "" // 这里作者备注给的空字符串
对应完整待签名交易数据
5354580012000022800000002400000007201b0000000b614000000000002710684000000000002710732103e7dfa41a3e7f626c5c0d1a2d8c0b1ac3baf6039bef1d1996993dc8f9dc816d3c811447923fc967fed6a696ec0cd3e2ae852901a9e8698314b53e0a778749318b634d1ed7c25667bb2b2412a3
解析交易数据
53545800 // 签名信息标记(0x53545800L),
12 // TransactionType标记 payment为“0000”是uint16类型, 对应的Key等于2 而2小于0xf, 所以计算方式为 1 << 4 | key(key为1) 等于12 1<<4 = 10000(二进制) 转换为10进制等于16 16 | 2 等于18, 18转换为16进制等于12.
0000 // TransactionType 当前是Payment
22 // Flags 标记
80000000 // Flags 2147483648的十六进制形式展现
24 // Sequence 标记
00000007 // Sequence
20 // lastLedgerSequence type << 4 因为lastLedgerSequence 对应key为27,而27大于0xf,所以先拼接 type << 4 在拼接 key type << 4 = 32十六进制为20 key = 27 十六进制为1b
1b // lastLedgerSequence key27 = 1b
026F2922 // 最新总交易确认数 + 1000 转十六进制
61 // Fee 标记
4000000000002710 // Fee
68 // Amount 标记
4000000000002710 // Amount
73 // PublicKey 标记
21 // PublicKey len
03e7dfa41a3e7f626c5c0d1a2d8c0b1ac3baf6039bef1d1996993dc8f9dc816d3c // PublicKey
81 // Account 标记
14 // Account len
47923fc967fed6a696ec0cd3e2ae852901a9e869 // Account (就是公钥Hash160)
83 // Recipient 标记
14 // Recipient len
b53e0a778749318b634d1ed7c25667bb2b2412a3 // Recipient (就是公钥Hash160)
待广播交易数据解析
- 完整待广播的十六进制交易数据
12000022800000002400000007201B026F2922614000000000002710684000000000002
710732103E7DFA41A3E7F626C5C0D1A2D8C0B1AC3BAF6039BEF1D1996993DC8F9DC816
D3C744630440220725C375C8332302013F3E3B29C668400FB799A8D8315CFBF8C7E09B
D2000FA3902207800E6E06E1A5719B3B0970C10C49FCFDEBFFEB3067209BB0B5619E5D
BFBC8A2811447923FC967FED6A696EC0CD3E2AE852901A9E8698314B53E0A778749318
B634D1ED7C25667BB2B2412A3
- 十六进制交易数据解析
12 // TransactionType 标记
0000 // TransactionType 当前是Payment
22 // Flags 标记
80000000 // Flags 2147483648的十六进制形式展现
24 // Sequence 标记
00000007 // Sequence
20 // lastLedgerSequence type << 4
1b // lastLedgerSequence key
026F2922 // 最新总交易确认数 + 1000 转十六进制
61 // Fee 标记
4000000000002710 // Fee
68 // Amount 标记
4000000000002710 // Amount
73 // PublicKey 标记
21 // PublicKey len
03e7dfa41a3e7f626c5c0d1a2d8c0b1ac3baf6039bef1d1996993dc8f9dc816d3c // PublicKey
74 // Sign info 标记
46 // Sign info len
3044
02203beee4ff172a0dc9d0c5582d5d44bcee1cc7f2a5a2bc98729909ecfeb4cbefda
022056b3cdd7a142b043335dc351e016b81cf249663fb4e2224b0e6ca58723937f40 // Sign info
81 // Account 标记
14 // Account len
47923fc967fed6a696ec0cd3e2ae852901a9e869 // Account (就是公钥Hash160)
83 // Recipient 标记
14 // Recipient len
b53e0a778749318b634d1ed7c25667bb2b2412a3 // Recipient (就是公钥Hash160)
广播交易
- 广播成功,节点会返回一下内容
{
result = {
"engine_result" = tesSUCCESS;
"engine_result_code" = 0;
"engine_result_message" = "The transaction was applied. Only final in a validated ledger.";
status = success;
"tx_blob" = 120000228000000024000000026140000000000186A0684000000000002710732103E7DFA41A3E7F626C5C0D1A2D8C0B1AC3BAF6039BEF1D1996993DC8F9DC816D3C7447304502210095E65663549C2217FA6DCDD69703B2931E90469066476B386BF2E25E3E9ED03902200229E79FB9586E6498519C83242C04A85D5CC347F81576EDE16CCA8B82D13A2E811447923FC967FED6A696EC0CD3E2AE852901A9E8698314B53E0A778749318B634D1ED7C25667BB2B2412A3;
"tx_json" = {
Account = rfXSBUpv9Yr41q5qFGRo9LJi1Jbe1wNEFe;
Amount = 100000;
Destination = rHXKdQhjXUtotW3yaofmu3YyuSZ2FXfxFC;
Fee = 10000;
Flags = 2147483648;
Sequence = 2;
SigningPubKey = 03E7DFA41A3E7F626C5C0D1A2D8C0B1AC3BAF6039BEF1D1996993DC8F9DC816D3C;
TransactionType = Payment;
TxnSignature = 304502210095E65663549C2217FA6DCDD69703B2931E90469066476B386BF2E25E3E9ED03902200229E79FB9586E6498519C83242C04A85D5CC347F81576EDE16CCA8B82D13A2E;
hash = A675E3C64F7F93A97CA9E1BE93265C230A5D848594960605B7E684A688D39B87;
};
};
}
- 广播失败,节点有可能会返回一下内容:
{
result = {
"engine_result" = "tefMAX_LEDGER"; // ter,tef和tem 都为提交成功,但是是失败的 “tefMAX_LEDGER”。(它也可能因“tefALREADY”或“tefPAST_SEQ”而失败。)
"engine_result_code" = "-187";
"engine_result_message" = "Ledger sequence too high.";
status = success;
"tx_blob" = 12000022800000002400000007201B0000000B614000000000002710684000000000002710732103E7DFA41A3E7F626C5C0D1A2D8C0B1AC3BAF6039BEF1D1996993DC8F9DC816D3C7446304402203BEEE4FF172A0DC9D0C5582D5D44BCEE1CC7F2A5A2BC98729909ECFEB4CBEFDA022056B3CDD7A142B043335DC351E016B81CF249663FB4E2224B0E6CA58723937F40811447923FC967FED6A696EC0CD3E2AE852901A9E8698314B53E0A778749318B634D1ED7C25667BB2B2412A3;
"tx_json" = {
Account = rfXSBUpv9Yr41q5qFGRo9LJi1Jbe1wNEFe;
Amount = 10000;
Destination = rHXKdQhjXUtotW3yaofmu3YyuSZ2FXfxFC;
Fee = 10000;
Flags = 2147483648;
LastLedgerSequence = 11;
Sequence = 7;
SigningPubKey = 03E7DFA41A3E7F626C5C0D1A2D8C0B1AC3BAF6039BEF1D1996993DC8F9DC816D3C;
TransactionType = Payment;
TxnSignature = 304402203BEEE4FF172A0DC9D0C5582D5D44BCEE1CC7F2A5A2BC98729909ECFEB4CBEFDA022056B3CDD7A142B043335DC351E016B81CF249663FB4E2224B0E6CA58723937F40;
hash = 5DA0D0479087438F32C49709788ECAD3B5904DB119E5E4130BD2AF3ED5044900;
};
};
}
@end