18
18
19
19
package org .bitcoinj .core ;
20
20
21
- import java .io .IOException ;
22
- import java .io .ObjectInputStream ;
23
- import java .io .ObjectOutputStream ;
21
+ import static com .google .common .base .Preconditions .checkArgument ;
24
22
25
- import org .bitcoinj .params .Networks ;
26
- import org .bitcoinj .script .Script ;
23
+ import java .util .Arrays ;
27
24
28
25
import javax .annotation .Nullable ;
29
26
30
- import static com .google .common .base .Preconditions .checkArgument ;
31
- import static com .google .common .base .Preconditions .checkNotNull ;
27
+ import org .bitcoinj .params .Networks ;
28
+ import org .bitcoinj .script .Script ;
29
+
30
+ import com .google .common .base .Objects ;
32
31
33
32
/**
34
33
* <p>A Bitcoin address looks like 1MsScoe2fTJoq4ZPdQgqyhgWeoNamYPevy and is derived from an elliptic curve public key
@@ -47,26 +46,31 @@ public class Address extends VersionedChecksummedBytes {
47
46
*/
48
47
public static final int LENGTH = 20 ;
49
48
50
- private transient NetworkParameters params ;
49
+ /** True if P2SH, false if P2PKH. */
50
+ public final boolean p2sh ;
51
51
52
52
/**
53
53
* Construct an address from parameters, the address version, and the hash160 form. Example:<p>
54
54
*
55
55
* <pre>new Address(MainNetParams.get(), NetworkParameters.getAddressHeader(), Hex.decode("4a22c3c4cbb31e4d03b15550636762bda0baf85a"));</pre>
56
56
*/
57
- public Address (NetworkParameters params , int version , byte [] hash160 ) throws WrongNetworkException {
58
- super (version , hash160 );
59
- checkNotNull (params );
57
+ public Address (NetworkParameters params , boolean p2sh , byte [] hash160 ) throws WrongNetworkException {
58
+ super (params , hash160 );
60
59
checkArgument (hash160 .length == 20 , "Addresses are 160-bit hashes, so you must provide 20 bytes" );
61
- if (!isAcceptableVersion (params , version ))
62
- throw new WrongNetworkException (version );
63
- this .params = params ;
60
+ this .p2sh = p2sh ;
61
+ }
62
+
63
+ /**
64
+ * Constructs a P2PKH address.
65
+ */
66
+ public Address (NetworkParameters params , byte [] hash160 ) throws WrongNetworkException {
67
+ this (params , false , hash160 );
64
68
}
65
69
66
70
/** Returns an Address that represents the given P2SH script hash. */
67
71
public static Address fromP2SHHash (NetworkParameters params , byte [] hash160 ) {
68
72
try {
69
- return new Address (params , params . getP2SHHeader () , hash160 );
73
+ return new Address (params , true , hash160 );
70
74
} catch (WrongNetworkException e ) {
71
75
throw new RuntimeException (e ); // Cannot happen.
72
76
}
@@ -90,44 +94,31 @@ public static Address fromP2SHScript(NetworkParameters params, Script scriptPubK
90
94
* if the given address is valid but for a different chain (eg testnet vs mainnet)
91
95
*/
92
96
public static Address fromBase58 (@ Nullable NetworkParameters params , String base58 ) throws AddressFormatException {
93
- return new Address (params , base58 );
94
- }
95
-
96
- /**
97
- * Construct an address from parameters and the hash160 form. Example:<p>
98
- *
99
- * <pre>new Address(MainNetParams.get(), Hex.decode("4a22c3c4cbb31e4d03b15550636762bda0baf85a"));</pre>
100
- */
101
- public Address (NetworkParameters params , byte [] hash160 ) {
102
- super (params .getAddressHeader (), hash160 );
103
- checkArgument (hash160 .length == 20 , "Addresses are 160-bit hashes, so you must provide 20 bytes" );
104
- this .params = params ;
105
- }
106
-
107
- /** @deprecated Use {@link #fromBase58(NetworkParameters, String)} */
108
- @ Deprecated
109
- public Address (@ Nullable NetworkParameters params , String address ) throws AddressFormatException {
110
- super (address );
111
- if (params != null ) {
112
- if (!isAcceptableVersion (params , version )) {
113
- throw new WrongNetworkException (version );
114
- }
115
- this .params = params ;
116
- } else {
117
- NetworkParameters paramsFound = null ;
97
+ byte [] versionAndDataBytes = Base58 .decodeChecked (base58 );
98
+ int version = versionAndDataBytes [0 ] & 0xFF ;
99
+ byte [] bytes = Arrays .copyOfRange (versionAndDataBytes , 1 , versionAndDataBytes .length );
100
+ if (params == null ) {
118
101
for (NetworkParameters p : Networks .get ()) {
119
- if (isAcceptableVersion ( p , version )) {
120
- paramsFound = p ;
121
- break ;
122
- }
102
+ if (version == p . getAddressHeader ())
103
+ return new Address ( p , false , bytes ) ;
104
+ else if ( version == p . getP2SHHeader ())
105
+ return new Address ( p , true , bytes );
123
106
}
124
- if (paramsFound == null )
125
- throw new AddressFormatException ("No network found for " + address );
126
-
127
- this .params = paramsFound ;
107
+ throw new AddressFormatException ("No network found for " + base58 );
108
+ } else {
109
+ if (version == params .getAddressHeader ())
110
+ return new Address (params , false , bytes );
111
+ else if (version == params .getP2SHHeader ())
112
+ return new Address (params , true , bytes );
113
+ throw new WrongNetworkException (version );
128
114
}
129
115
}
130
116
117
+ @ Override
118
+ protected int getVersion () {
119
+ return p2sh ? params .getP2SHHeader () : params .getAddressHeader ();
120
+ }
121
+
131
122
/** The (big endian) 20 byte hash that is the core of a Bitcoin address. */
132
123
public byte [] getHash160 () {
133
124
return bytes ;
@@ -138,8 +129,7 @@ public byte[] getHash160() {
138
129
* See also https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki: Address Format for pay-to-script-hash
139
130
*/
140
131
public boolean isP2SHAddress () {
141
- final NetworkParameters parameters = getParameters ();
142
- return parameters != null && this .version == parameters .p2shHeader ;
132
+ return p2sh ;
143
133
}
144
134
145
135
/**
@@ -169,15 +159,19 @@ public static NetworkParameters getParametersFromAddress(String address) throws
169
159
}
170
160
}
171
161
172
- /**
173
- * Check if a given address version is valid given the NetworkParameters.
174
- */
175
- private static boolean isAcceptableVersion (NetworkParameters params , int version ) {
176
- if (version == params .getAddressHeader ())
177
- return true ;
178
- if (version == params .getP2SHHeader ())
162
+ @ Override
163
+ public boolean equals (Object o ) {
164
+ if (this == o )
179
165
return true ;
180
- return false ;
166
+ if (o == null || getClass () != o .getClass ())
167
+ return false ;
168
+ Address other = (Address ) o ;
169
+ return super .equals (other ) && this .p2sh == other .p2sh ;
170
+ }
171
+
172
+ @ Override
173
+ public int hashCode () {
174
+ return Objects .hashCode (super .hashCode (), p2sh );
181
175
}
182
176
183
177
/**
@@ -187,16 +181,4 @@ private static boolean isAcceptableVersion(NetworkParameters params, int version
187
181
public Address clone () throws CloneNotSupportedException {
188
182
return (Address ) super .clone ();
189
183
}
190
-
191
- // Java serialization
192
-
193
- private void writeObject (ObjectOutputStream out ) throws IOException {
194
- out .defaultWriteObject ();
195
- out .writeUTF (params .id );
196
- }
197
-
198
- private void readObject (ObjectInputStream in ) throws IOException , ClassNotFoundException {
199
- in .defaultReadObject ();
200
- params = NetworkParameters .fromID (in .readUTF ());
201
- }
202
184
}
0 commit comments