Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

Bytom Java版本离线签名

华胥
96 0 0
比原项目仓库:, m. ^+ }, q4 s
Github地址:https://github.com/Bytom/bytom
- m3 H  b% \" [3 @4 TGitee地址:https://gitee.com/BytomBlockchain/bytom% Y) W4 e7 ?% h" Q
tx_signer" S. Y: z1 f8 c, E( i
Java implementation of signing transaction offline to bytomd.( b# E: Q* F$ d2 w! `
Pre
; J. C2 E7 Y+ MGet the source code
) S4 B9 t) _# r1 T  r& S$ git clone https://github.com/Bytom/bytom.git $GOPATH/src/github.com/bytom( ?! ]% @4 V$ H7 j
git checkout
. P9 C5 v% y1 i0 c9 i$ git checkout dev- w- c3 G7 i% V, {3 Q8 F
Why need dev branch? Because you could call decode transaction api from dev branch and obtain tx_id and some inputs ids.
6 g/ M+ ~) L3 a7 R+ ^  @5 OBuild
" o# @7 N0 Q# G7 f2 ~$ cd $GOPATH/src/github.com/bytom  U( ^, f8 Q2 G
$ make bytomd    # build bytomd/ Q- A5 r$ c/ z
$ make bytomcli  # build bytomcli) w8 c: d) ?; u' b/ _8 l
When successfully building the project, the bytom and bytomcli binary should be present in cmd/bytomd and cmd/bytomcli directory, respectively.
4 E* E/ @6 k; n+ {: _& mInitialize0 L6 T- F: e+ s3 v
First of all, initialize the node:
' j2 l! }! x* j7 x$ cd ./cmd/bytomd
- G2 q% G4 M6 ]( s; V+ i9 N$ ./bytomd init --chain_id solonet7 K* }6 F. R4 ], L$ B4 Y% s  E
launch  u) q$ d% e! u& c9 f
$ ./bytomd node --mining
5 g( z( h; G! V# A4 aUsage* _+ l7 o) v& h! N" o
Build jar2 e+ J" [' _- U$ S

  • + f3 `  w$ E/ \' Bfirst get source code
    ) x; b- w* b+ Y  S  k. Z9 a0 Egit clone https://github.com/successli/tx_signer.git2 W! i5 G8 d8 p/ S$ \
  • + b4 n/ ^/ Z' R/ i" g) i8 f
    get jar package
    ; f; j2 r; \5 L+ o$ mvn assembly:assembly -Dmaven.test.skip=true
    ) @  r$ M6 Q4 n# t) b# E3 H2 jYou can get a jar with dependencies, and you can use it in your project.4 a1 B2 i& }7 k$ R8 p

    7 ?0 O  S3 q+ R
    ; ^" }! S, d# |: p4 X% [Test cases
    ( |" y! _3 e$ r2 e$ t  FNeed 3 Parameters:
    ( Y; P: D! f; Q6 J, X' L
  • Private Keys Array
  • Template Object
  • After call build transaction api return a Template json object. build transaction api
  • use bytom java sdk return a Template object.
  • Raw Transaction
  • call decode raw-transaction api from dev branch. decode raw-transaction api" r6 o8 }+ }6 _; o

    ! ]. t5 B( z( N5 K0 t( XCall method:; K  Z% w; u- B( `: E& O2 B
    // return a Template object signed offline basically.+ P) Q5 ?1 [% ^' {* m3 o. e
    Template result = signatures.generateSignatures(privates, template, rawTransaction);: _; Y. ?" e) q& Q' `. P9 ^
    // use result's raw_transaction call sign transaction api to build another data but not need password or private key.6 b/ S- \6 |3 P: k
    Single-key Example:
    ' B! c1 e" _. a. a@Test  d2 c9 d/ x- N: }1 d  o: U* y, X
    // 使用 SDK 来构造 Template 对象参数, 单签
    1 i5 l$ u! y% }* {4 kpublic void testSignSingleKey() throws BytomException {+ D- H) z1 T' j. [
        Client client = Client.generateClient();" ~& ~5 G6 Y7 X" o2 q
        String asset_id = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
    / T3 a* ?' J) Y8 F# _& v# V. s    String address = "sm1qvyus3s5d7jv782syuqe3qrh65fx23lgpzf33em";
    9 @3 m; m3 ?4 ^6 d4 ]    // build transaction obtain a Template object
    8 g1 X/ E3 i# ^8 _4 S1 ?0 f* g    Template template = new Transaction.Builder()
    0 m- Q4 I: f3 c4 m3 [        .addAction(
    : R8 W! d8 a. e/ o; X$ I& U& y        new Transaction.Action.SpendFromAccount()$ g) s  d; f3 s+ S* h! A
            .setAccountId("0G0NLBNU00A02")$ i- a9 l5 o. S7 c+ ~) e+ O+ F$ L
            .setAssetId(asset_id)2 O: l1 W$ q- f; @  e
            .setAmount(40000000)
    ! }; @* G* n  P0 j    )' ?5 b: h( ]  x3 w
            .addAction(
    , `; k$ V: K7 u! E4 [1 f        new Transaction.Action.SpendFromAccount()  M" t: T0 [# w3 U  C, b
            .setAccountId("0G0NLBNU00A02")7 D2 [8 f# O6 s, m1 n
            .setAssetId(asset_id)
    : K" J$ p8 v) }$ [4 w! T        .setAmount(300000000)4 a9 S# W8 G  X
        )
    $ Y9 d7 |* m, Q: B% u$ [        .addAction(3 m( b6 m2 m. S0 [+ j
            new Transaction.Action.ControlWithAddress()
    * B$ N* E$ ?. t        .setAddress(address)
      f/ `2 \. n% ?; n) L        .setAssetId(asset_id)" L7 B6 x& J2 E! D& x
            .setAmount(30000000)& W1 z* c3 @3 f( I7 _
        ).build(client);4 K* g) r. x& i* B- M2 `5 d2 t
        logger.info("template: " + template.toJson());
    ; U- F3 e/ p9 K* P    // use Template object's raw_transaction id to decode raw_transaction obtain a RawTransaction object
    $ N! s7 `  p: F: f    RawTransaction decodedTx = RawTransaction.decode(client, template.rawTransaction);7 y( K9 T! j! J3 L+ e& o0 i
        logger.info("decodeTx: " + decodedTx.toJson());
    2 }, S3 I) g  a- v    // need a private key array
    " Y% c$ ]5 D0 @4 x% n8 D8 I    String[] privateKeys = new String[]{"10fdbc41a4d3b8e5a0f50dd3905c1660e7476d4db3dbd9454fa4347500a633531c487e8174ffc0cfa76c3be6833111a9b8cd94446e37a76ee18bb21a7d6ea66b"};. J8 |0 m/ _8 y
        logger.info("private key:" + privateKeys[0]);
    5 A1 r  W8 i9 i) Y0 d    // call offline sign method to obtain a basic offline signed template/ ?3 i7 }: N) @* `" ?+ e) i8 R+ I
        Signatures signatures = new SignaturesImpl();
    / s4 H* H  Q0 P- \9 }2 I( w8 k0 \    Template basicSigned = signatures.generateSignatures(privateKeys, template, decodedTx);
    ! `, R' Q" A" s* U8 m2 C  P/ H7 I    logger.info("basic signed raw: " + basicSigned.toJson());
    ! u- N% W( P/ ^- c- Y    // call sign transaction api to calculate whole raw_transaction id$ \/ E4 N) M  e; P/ S' L
        // sign password is None or another random String
    ! G1 _7 Y7 ^4 w$ y5 O    Template result = new Transaction.SignerBuilder().sign(client," O5 b4 c5 S4 R) o
                                                               basicSigned, "");
    : o0 c! E4 w! A2 B6 R    logger.info("result raw_transaction: " + result.toJson());- U3 p' c2 y+ G" J1 ?! [% U, R
        // success to submit transaction
    - R8 l& ]1 {' z! B9 M, Q) g# w}
    , F3 I0 o' Y; h" Y$ PMulti-keys Example:
    9 E8 @/ g) _' Y$ X! d. F, p! `- ]" D
    Need an account has two or more keys." s; n0 t" K8 w! ?/ g
    5 Y0 A. a9 E! R+ n. O# k
    @Test4 v9 _4 g( [# n- Y. `. P6 X
    // 使用 SDK 来构造 Template 对象参数, 多签
    % W3 g! ]% ^. A9 `1 f8 h) ^% ~6 ppublic void testSignMultiKeys() throws BytomException {
    + ~0 U! O# D" J5 |    Client client = Client.generateClient();2 s: k2 g5 q4 h
        String asset_id = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";/ p1 ^4 V% P* }" b% k& ^: P$ W
        String address = "sm1qvyus3s5d7jv782syuqe3qrh65fx23lgpzf33em";
    6 l1 O; K' X6 h" R9 L) L# E# }$ S    // build transaction obtain a Template object
    - }' h# {" H( G, y# l+ d8 i  H    // account 0G1RPP6OG0A06 has two keys* Y* q& \3 z2 y2 v$ C
        Template template = new Transaction.Builder()
    / L: K5 X, [" b  R        .setTtl(10)6 q; a$ Z' ~* s& [4 Z% b/ ]1 K7 R
            .addAction(% P, W: T2 H0 R& q( D1 h$ x0 s
            new Transaction.Action.SpendFromAccount()
    1 v2 w0 R! ~/ g3 t        .setAccountId("0G1RPP6OG0A06")% a) j1 m) V9 I% j. O6 W$ }9 y
            .setAssetId(asset_id)0 H' ~% C7 n* W* W( z4 z
            .setAmount(40000000)
    8 W( W* q0 M3 V$ V2 n# q( N    )5 S: x8 S, W: K. }
            .addAction(: B% W+ A3 ^2 |0 Q4 @
            new Transaction.Action.SpendFromAccount()
    6 B% f5 W/ P( z8 i. t  K6 A7 U        .setAccountId("0G1RPP6OG0A06")
    , i# o- f2 l) g1 r- Y! n        .setAssetId(asset_id). v# D5 ?- d' i+ f  Z6 o
            .setAmount(300000000)
    ! M! G! ^* Q2 ~2 h3 |% N: V    )( }! |; V  ]" k- M
            .addAction(
    7 Z% Z: z6 s& s* D& E" y' b- V. c        new Transaction.Action.ControlWithAddress()0 X( [, @, A; Y6 i5 x0 G( a
            .setAddress(address)
    # F: \: M5 N7 `6 r; N        .setAssetId(asset_id)
    7 a& |* [* W: z2 [. e* A2 a        .setAmount(30000000)
    / ]" E! ^& \$ k" |: ^% n" O    ).build(client);! e9 G9 e! d# \) c6 f; a( i
        logger.info("template: " + template.toJson());- w6 U# s. W' [' [' Q: T3 H: J
        // use Template object's raw_transaction id to decode raw_transaction obtain a RawTransaction object2 Y$ b. L/ p" @" ?# j/ B% W* Q
        RawTransaction decodedTx = RawTransaction.decode(client, template.rawTransaction);
    9 ?7 n4 P4 v7 Z. L1 i9 p" `    logger.info("decodeTx: " + decodedTx.toJson());
    2 V" p/ b# @" v4 _" |8 M# K    // need a private key array1 @5 r* D( J) b5 H
        String[] privateKeys = new String[]{"08bdbd6c22856c5747c930f64d0e5d58ded17c4473910c6c0c3f94e485833a436247976253c8e29e961041ad8dfad9309744255364323163837cbef2483b4f67",: L1 @: b" l+ q% B
                                            "40c821f736f60805ad59b1fea158762fa6355e258601dfb49dda6f672092ae5adf072d5cab2ceaaa0d68dd3fe7fa04869d95afed8c20069f446a338576901e1b"};
    ( g0 q7 M, D% t/ x8 U/ c    logger.info("private key 1:" + privateKeys[0]);
    : @! Z4 V" B1 j' U, s    logger.info("private key 2:" + privateKeys[1]);! f6 v+ J) T, s! B9 @: e$ B
        // call offline sign method to obtain a basic offline signed template
    1 |6 @4 g. E: J, R    Signatures signatures = new SignaturesImpl();
    8 b+ c4 ]0 C% D/ e9 M" W    Template basicSigned = signatures.generateSignatures(privateKeys, template, decodedTx);! m8 |- L, n! p1 S
        logger.info("basic signed raw: " + basicSigned.toJson());
    + A0 o' U& U! x/ J6 _1 Y; @    // call sign transaction api to calculate whole raw_transaction id2 I4 b& f" T& Z
        // sign password is None or another random String
    + E" x- f9 L( M! C, I/ I8 R    Template result = new Transaction.SignerBuilder().sign(client,
    9 k% l! a; G- E# w                                                           basicSigned, "");" z" r9 s0 p7 `4 e$ K$ E7 D: M+ S+ }
        logger.info("result raw_transaction: " + result.toJson());
    $ i  S1 ?8 P) E" S9 z    // success to submit transaction
    * s8 ], J. z2 C1 B7 o4 d}4 ]6 ?: T& t! R$ ]7 H) i
    Multi-keys and Multi-inputs Example:* ^5 G! Q! ]8 A4 a  Z: c
    @Test
    8 u6 G- u% s2 F" ?$ G# [// 使用 SDK 来构造 Template 对象参数, 多签, 多输入" j" Z8 l2 Y- T! S. D; D* w
    public void testSignMultiKeysMultiInputs() throws BytomException {
    - M* n+ ]  M4 ~+ P: k* m+ V    Client client = Client.generateClient();; W/ C1 q5 O. B
        String asset_id = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
    * g8 i( n* x0 w( g    String address = "sm1qvyus3s5d7jv782syuqe3qrh65fx23lgpzf33em";8 V9 v( z. c$ [4 W7 w5 n
        // build transaction obtain a Template object( \' U1 H) d, i+ A  D
        Template template = new Transaction.Builder()) U  Q7 d' c! y
            .setTtl(10)
    ' I$ b1 M" o$ X, f, {        // 1 input
    . O5 `: t$ E6 j$ o. i        .addAction($ d3 J: G' D3 Y( ^! Z5 `  m& n
            new Transaction.Action.SpendFromAccount()# D+ @' i9 f) U) {( F
            .setAccountId("0G1RPP6OG0A06") // Multi-keys account
    : i' |+ B2 e9 [        .setAssetId(asset_id)
    0 _) A! p% [& v        .setAmount(40000000)2 Q6 g" P7 ]7 i, ^0 _3 P
        )2 J/ G/ M4 L+ ^% q/ K
            .addAction(. k% c7 }6 ^* I1 R
            new Transaction.Action.SpendFromAccount()
    8 |# b% N* j- |5 j! l2 p; ]. \        .setAccountId("0G1RPP6OG0A06")& n/ u- Q5 `* j0 e
            .setAssetId(asset_id)
      \$ m; R6 e8 B) m3 L' I9 u- q        .setAmount(300000000)
    2 |! I; E$ g( D% \8 Q3 z$ p    )    // 2 input8 f% F) d( n& Q' m# W. |  ^8 Y
            .addAction(, A' X( t! L! E* C% W; M8 [* B- b
            new Transaction.Action.SpendFromAccount()# n" s+ x' f; t* k" t' T9 y; R$ j
            .setAccountId("0G1Q6V1P00A02") // Multi-keys account
    , I- t+ j% K# B. y  m        .setAssetId(asset_id)# [. u: n! O1 f  C) ~) Y9 @  M) H. G
            .setAmount(40000000)
    2 ]. N* s$ b4 {    )
    ) F" w* A9 W/ g/ n' H( \        .addAction(
    ' U0 B7 M, `' |* A& H( y6 V        new Transaction.Action.SpendFromAccount()* [4 t2 j7 f% y- M* _4 Q6 O
            .setAccountId("0G1Q6V1P00A02")4 B) x4 S8 I5 H2 U$ K0 b- v% D
            .setAssetId(asset_id): U* Z& f6 l5 G4 T& g
            .setAmount(300000000)
    : X0 t2 M$ X! I/ Q4 o6 e1 ]1 T/ v    )5 {. ?" F6 {0 j8 Z( J) j
            .addAction(
    . s' t8 e7 S& [( ]        new Transaction.Action.ControlWithAddress()
    . T9 L* ?1 ?) I4 z9 r        .setAddress(address)" J" H0 S4 A& H% r' e
            .setAssetId(asset_id)
    . K/ t3 B5 ~8 @; B/ q        .setAmount(60000000): d5 m7 r0 q* A8 o. {- b6 ]8 @
        ).build(client);
    - F1 ~# J7 z8 J: V3 k$ s5 J    logger.info("template: " + template.toJson());
    ( V! D2 r( p/ p1 d7 ^4 ^    // use Template object's raw_transaction id to decode raw_transaction obtain a RawTransaction object
    ! K/ s) P) ]* T6 x5 J    RawTransaction decodedTx = RawTransaction.decode(client, template.rawTransaction);
    & H+ r3 d: m5 z- b    logger.info("decodeTx: " + decodedTx.toJson());! A" v% R5 {  M, u7 @1 G2 N
        // need a private key array* A% [8 b, o3 s" L+ w" u, R6 Q
        String[] privateKeys = new String[]{"08bdbd6c22856c5747c930f64d0e5d58ded17c4473910c6c0c3f94e485833a436247976253c8e29e961041ad8dfad9309744255364323163837cbef2483b4f67",
    , S, k: z7 \' U% C' U. B6 G& w                                        "40c821f736f60805ad59b1fea158762fa6355e258601dfb49dda6f672092ae5adf072d5cab2ceaaa0d68dd3fe7fa04869d95afed8c20069f446a338576901e1b",
    # P9 P5 H; M( S) J- ]; _                                        "08bdbd6c22856c5747c930f64d0e5d58ded17c4473910c6c0c3f94e485833a436247976253c8e29e961041ad8dfad9309744255364323163837cbef2483b4f67"};
      j8 D, z' t9 {, K    logger.info("private key 1:" + privateKeys[0]);
    5 U, I1 o$ R: y# g& J    logger.info("private key 2:" + privateKeys[1]);
    " `4 ?( E0 A2 [& B    // call offline sign method to obtain a basic offline signed template
    9 k2 v8 q! c$ u8 h+ H2 [& ?$ R5 ~    Signatures signatures = new SignaturesImpl();. [* `+ J2 d9 x% g' p, D; m, D
        Template basicSigned = signatures.generateSignatures(privateKeys, template, decodedTx);
    1 W4 _5 J+ H6 d    logger.info("basic signed raw: " + basicSigned.toJson());# O6 N' P: j7 o  @; f$ w: x7 Q& {
        // call sign transaction api to calculate whole raw_transaction id- a$ H" j8 p7 m! H2 T7 V2 n
        // sign password is None or another random String* x! o# S1 H7 o* [/ X
        Template result = new Transaction.SignerBuilder().sign(client,
    . H( ^. @5 I/ z3 D- h* N' _# p) t                                                           basicSigned, "");
    ; R7 y) e+ M. A* z; o; C# C& L    logger.info("result raw_transaction: " + result.toJson());
    ) y9 t! q* v- x' }+ |    // success to submit transaction
    8 K9 {% E5 M, f- R  D}
  • BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
    声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    成为第一个吐槽的人

    华胥 初中生
    • 粉丝

      0

    • 关注

      0

    • 主题

      13