11const bignum = require ( 'bignum' ) ;
22const base58 = require ( 'base58-native' ) ;
3+ const bech32 = require ( 'bech32' ) ;
34const bitcoin = require ( 'bitcoinjs-lib' ) ;
45
56const diff1 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ;
@@ -148,14 +149,20 @@ function getTransactionBuffers(txs) {
148149}
149150
150151function addressToScript ( addr ) {
151- const decoded = base58 . decode ( addr ) ;
152- if ( decoded . length != 25 ) throw new Error ( 'Invalid address length for ' + addr ) ;
153- if ( ! decoded ) throw new Error ( 'Base58 decode failed for ' + addr ) ;
152+ let decoded ;
153+ try {
154+ decoded = base58 . decode ( addr ) ;
155+ } catch ( err ) { }
156+ if ( ! decoded || decoded . length != 25 ) {
157+ const decoded2 = Buffer . from ( bech32 . bech32 . fromWords ( bech32 . bech32 . decode ( addr ) . words . slice ( 1 ) ) ) ;
158+ if ( decoded2 . length != 20 ) throw new Error ( 'Invalid address ' + addr ) ;
159+ return Buffer . concat ( [ Buffer . from ( [ 0x0 , 0x14 ] ) , decoded2 ] ) ;
160+ }
154161 const pubkey = decoded . slice ( 1 , - 4 ) ;
155162 return Buffer . concat ( [ Buffer . from ( [ 0x76 , 0xa9 , 0x14 ] ) , pubkey , Buffer . from ( [ 0x88 , 0xac ] ) ] ) ;
156163}
157164
158- function createOutputTransaction ( amount , payee , rewardToPool , reward , txOutputBuffers , payeeScript ) {
165+ function createTransactionOutput ( amount , payee , rewardToPool , reward , txOutputBuffers , payeeScript ) {
159166 const payeeReward = amount ;
160167 if ( ! payeeScript ) payeeScript = addressToScript ( payee ) ;
161168 txOutputBuffers . push ( Buffer . concat ( [
@@ -166,19 +173,25 @@ function createOutputTransaction(amount, payee, rewardToPool, reward, txOutputBu
166173 return { reward : reward - amount , rewardToPool : rewardToPool - amount } ;
167174}
168175
169- function generateOutputTransactions ( rpcData , poolAddress ) {
170- let reward = rpcData . coinbasevalue ;
176+ function generateTransactionOutputs ( rpcData , poolAddress ) {
177+ let reward = rpcData . coinbasevalue + ( rpcData . coinbasedevreward ? rpcData . coinbasedevreward . value : 0 ) ;
171178 let rewardToPool = reward ;
172179 let txOutputBuffers = [ ] ;
173180
181+ if ( rpcData . coinbasedevreward ) {
182+ const rewards = createTransactionOutput ( rpcData . coinbasedevreward . value , null , rewardToPool , reward , txOutputBuffers , Buffer . from ( rpcData . coinbasedevreward . scriptpubkey , 'hex' ) ) ;
183+ reward = rewards . reward ;
184+ rewardToPool = rewards . rewardToPool ;
185+ }
186+
174187 if ( rpcData . smartnode ) {
175188 if ( rpcData . smartnode . payee ) {
176- const rewards = createOutputTransaction ( rpcData . smartnode . amount , rpcData . smartnode . payee , rewardToPool , reward , txOutputBuffers ) ;
189+ const rewards = createTransactionOutput ( rpcData . smartnode . amount , rpcData . smartnode . payee , rewardToPool , reward , txOutputBuffers ) ;
177190 reward = rewards . reward ;
178191 rewardToPool = rewards . rewardToPool ;
179192 } else if ( Array . isArray ( rpcData . smartnode ) ) {
180193 for ( let i in rpcData . smartnode ) {
181- const rewards = createOutputTransaction ( rpcData . smartnode [ i ] . amount , rpcData . smartnode [ i ] . payee , rewardToPool , reward , txOutputBuffers ) ;
194+ const rewards = createTransactionOutput ( rpcData . smartnode [ i ] . amount , rpcData . smartnode [ i ] . payee , rewardToPool , reward , txOutputBuffers ) ;
182195 reward = rewards . reward ;
183196 rewardToPool = rewards . rewardToPool ;
184197 }
@@ -187,49 +200,52 @@ function generateOutputTransactions(rpcData, poolAddress) {
187200
188201 if ( rpcData . superblock ) {
189202 for ( let i in rpcData . superblock ) {
190- const rewards = createOutputTransaction ( rpcData . superblock [ i ] . amount , rpcData . superblock [ i ] . payee , rewardToPool , reward , txOutputBuffers ) ;
203+ const rewards = createTransactionOutput ( rpcData . superblock [ i ] . amount , rpcData . superblock [ i ] . payee , rewardToPool , reward , txOutputBuffers ) ;
191204 reward = rewards . reward ;
192205 rewardToPool = rewards . rewardToPool ;
193206 }
194207 }
195208
196209 if ( rpcData . founder_payments_started && rpcData . founder ) {
197210 const founderReward = rpcData . founder . amount || 0 ;
198- const rewards = createOutputTransaction ( founderReward , rpcData . founder . payee , rewardToPool , reward , txOutputBuffers ) ;
211+ const rewards = createTransactionOutput ( founderReward , rpcData . founder . payee , rewardToPool , reward , txOutputBuffers ) ;
199212 reward = rewards . reward ;
200213 rewardToPool = rewards . rewardToPool ;
201214 }
202215
203- createOutputTransaction ( rewardToPool , null , rewardToPool , reward , txOutputBuffers , Buffer . from ( addressToScript ( poolAddress ) , "hex" ) ) ;
216+ createTransactionOutput ( rewardToPool , null , rewardToPool , reward , txOutputBuffers , Buffer . from ( addressToScript ( poolAddress ) , "hex" ) ) ;
204217
205- if ( rpcData . default_witness_commitment !== undefined ) {
206- const witness_commitment = Buffer . from ( rpcData . default_witness_commitment , 'hex' ) ;
207- txOutputBuffers . unshift ( Buffer . concat ( [
208- packInt64LE ( 0 ) ,
209- varIntBuffer ( witness_commitment . length ) ,
210- witness_commitment
218+ if ( rpcData . default_witness_commitment ) {
219+ createTransactionOutput ( 0 , null , rewardToPool , reward , txOutputBuffers , Buffer . from ( rpcData . default_witness_commitment , 'hex' ) ) ;
220+ txOutputBuffers . push ( Buffer . concat ( [
221+ varIntBuffer ( 1 ) ,
222+ varIntBuffer ( 32 ) ,
223+ Buffer . alloc ( 32 , 0 )
211224 ] ) ) ;
212225 }
213226
214- return Buffer . concat ( [ varIntBuffer ( txOutputBuffers . length ) , Buffer . concat ( txOutputBuffers ) ] ) ;
227+ return Buffer . concat ( [ varIntBuffer ( rpcData . default_witness_commitment ? txOutputBuffers . length - 1 : txOutputBuffers . length ) , Buffer . concat ( txOutputBuffers ) ] ) ;
215228}
216229
217230module . exports . RtmBlockTemplate = function ( rpcData , poolAddress ) {
218231 const extraNoncePlaceholderLength = 17 ;
219- const coinbaseVersion = Buffer . concat ( [ packUInt16LE ( 3 ) , packUInt16LE ( 5 ) ] ) ;
232+ const coinbaseVersion = rpcData . coinbasedevreward ? Buffer . concat ( [ packUInt16LE ( 1 ) , packUInt16LE ( 0 ) ] ) : Buffer . concat ( [ packUInt16LE ( 3 ) , packUInt16LE ( 5 ) ] ) ;
220233
221234 const scriptSigPart1 = Buffer . concat ( [
222235 serializeNumber ( rpcData . height ) ,
223- Buffer . from ( rpcData . coinbaseaux . flags , 'hex' ) ,
236+ Buffer . from ( rpcData . coinbaseaux . flags ? rpcData . coinbaseaux . flags : "" , 'hex' ) ,
224237 serializeNumber ( Date . now ( ) / 1000 | 0 ) ,
225238 Buffer . from ( [ extraNoncePlaceholderLength ] )
226239 ] ) ;
227240
228241 const scriptSigPart2 = serializeString ( '/nodeStratum/' ) ;
229242
243+ const is_witness = rpcData . default_witness_commitment !== undefined ;
244+
230245 const blob1 = Buffer . concat ( [
231246 coinbaseVersion ,
232247 // transaction input
248+ Buffer . from ( is_witness ? "0001" : "" , 'hex' ) ,
233249 varIntBuffer ( 1 ) , // txInputsCount
234250 uint256BufferFromHash ( "" ) , // txInPrevOutHash
235251 packUInt32LE ( Math . pow ( 2 , 32 ) - 1 ) , // txInPrevOutIndex
@@ -242,13 +258,19 @@ module.exports.RtmBlockTemplate = function(rpcData, poolAddress) {
242258 packUInt32LE ( 0 ) , // txInSequence
243259 // end transaction input
244260 // transaction output
245- generateOutputTransactions ( rpcData , poolAddress ) ,
261+ generateTransactionOutputs ( rpcData , poolAddress , is_witness ) ,
246262 // end transaction ouput
247- packUInt32LE ( 0 ) , // txLockTime
248- varIntBuffer ( rpcData . coinbase_payload . length / 2 ) ,
249- Buffer . from ( rpcData . coinbase_payload , 'hex' )
263+ packUInt32LE ( 0 ) // txLockTime
250264 ] ) ;
251265
266+ if ( rpcData . coinbase_payload ) {
267+ blob2 = Buffer . concat ( [
268+ blob2 ,
269+ varIntBuffer ( rpcData . coinbase_payload . length / 2 ) ,
270+ Buffer . from ( rpcData . coinbase_payload , 'hex' )
271+ ] ) ;
272+ }
273+
252274 const prev_hash = reverseBuffer ( Buffer . from ( rpcData . previousblockhash , 'hex' ) ) . toString ( 'hex' ) ;
253275 const version = packInt32LE ( rpcData . version ) . toString ( 'hex' ) ;
254276 const curtime = packUInt32LE ( rpcData . curtime ) . toString ( 'hex' ) ;
0 commit comments