@@ -81,7 +81,12 @@ public override ContractCodeHashList GetContractCodeHashListByDeployingBlockHeig
81
81
public override Int32Value GetContractProposalExpirationTimePeriod ( Empty input )
82
82
{
83
83
var expirationTimePeriod = GetCurrentContractProposalExpirationTimePeriod ( ) ;
84
- return new Int32Value { Value = expirationTimePeriod } ;
84
+ return new Int32Value { Value = expirationTimePeriod } ;
85
+ }
86
+
87
+ public override Address GetSigner ( Address input )
88
+ {
89
+ return State . SignerMap [ input ] ;
85
90
}
86
91
87
92
#endregion Views
@@ -111,12 +116,23 @@ public override Address DeploySystemSmartContract(SystemContractDeploymentInput
111
116
public override Hash ProposeNewContract ( ContractDeploymentInput input )
112
117
{
113
118
// AssertDeploymentProposerAuthority(Context.Sender);
114
- AssertContractExists ( HashHelper . ComputeFrom ( input . Code . ToByteArray ( ) ) ) ;
119
+ var codeHash = HashHelper . ComputeFrom ( input . Code . ToByteArray ( ) ) ;
120
+ AssertContractNotExists ( codeHash ) ;
115
121
var proposedContractInputHash = CalculateHashFromInput ( input ) ;
116
122
RegisterContractProposingData ( proposedContractInputHash ) ;
117
-
123
+
118
124
var expirationTimePeriod = GetCurrentContractProposalExpirationTimePeriod ( ) ;
119
125
126
+ if ( input . ContractOperation != null )
127
+ {
128
+ ValidateContractOperation ( input . ContractOperation , 0 , codeHash ) ;
129
+
130
+ // Remove one time signer if exists. Signer is only needed for validating signature.
131
+ RemoveOneTimeSigner ( input . ContractOperation . Deployer ) ;
132
+
133
+ AssertContractAddressAvailable ( input . ContractOperation . Deployer , input . ContractOperation . Salt ) ;
134
+ }
135
+
120
136
// Create proposal for deployment
121
137
var proposalCreationInput = new CreateProposalBySystemContractInput
122
138
{
@@ -160,7 +176,19 @@ public override Hash ProposeUpdateContract(ContractUpdateInput input)
160
176
Assert ( info != null , "Contract not found." ) ;
161
177
AssertAuthorityByContractInfo ( info , Context . Sender ) ;
162
178
AssertContractVersion ( info . ContractVersion , input . Code , info . Category ) ;
163
- AssertContractExists ( HashHelper . ComputeFrom ( input . Code . ToByteArray ( ) ) ) ;
179
+
180
+ var codeHash = HashHelper . ComputeFrom ( input . Code . ToByteArray ( ) ) ;
181
+ AssertContractNotExists ( codeHash ) ;
182
+
183
+ Assert ( ( input . Address == Context . Self || info . SerialNumber > 0 ) && input . ContractOperation == null ||
184
+ info . SerialNumber == 0 && input . ContractOperation != null , "Not compatible." ) ;
185
+
186
+ if ( input . ContractOperation != null )
187
+ {
188
+ ValidateContractOperation ( input . ContractOperation , info . Version , codeHash ) ;
189
+ RemoveOneTimeSigner ( input . ContractOperation . Deployer ) ;
190
+ AssertSameDeployer ( input . Address , input . ContractOperation . Deployer ) ;
191
+ }
164
192
165
193
var expirationTimePeriod = GetCurrentContractProposalExpirationTimePeriod ( ) ;
166
194
@@ -282,7 +310,8 @@ public override Address DeploySmartContract(ContractDeploymentInput input)
282
310
283
311
var address =
284
312
DeploySmartContract ( null , input . Category , input . Code . ToByteArray ( ) , false ,
285
- DecideNonSystemContractAuthor ( contractProposingInput ? . Proposer , Context . Sender ) , false ) ;
313
+ DecideNonSystemContractAuthor ( contractProposingInput ? . Proposer , Context . Sender ) , false ,
314
+ input . ContractOperation ? . Deployer , input . ContractOperation ? . Salt ) ;
286
315
return address ;
287
316
}
288
317
@@ -297,7 +326,7 @@ public override Address UpdateSmartContract(ContractUpdateInput input)
297
326
Assert ( Context . Sender == info . Author , "No permission." ) ;
298
327
299
328
UpdateSmartContract ( contractAddress , input . Code . ToByteArray ( ) , info . Author , false ) ;
300
-
329
+
301
330
return contractAddress ;
302
331
}
303
332
@@ -362,17 +391,22 @@ public override Empty SetContractProposalExpirationTimePeriod(SetContractProposa
362
391
State . ContractProposalExpirationTimePeriod . Value = input . ExpirationTimePeriod ;
363
392
return new Empty ( ) ;
364
393
}
365
-
366
- public override DeployUserSmartContractOutput DeployUserSmartContract ( ContractDeploymentInput input )
394
+
395
+ public override DeployUserSmartContractOutput DeployUserSmartContract ( UserContractDeploymentInput input )
367
396
{
368
397
AssertInlineDeployOrUpdateUserContract ( ) ;
369
398
AssertUserDeployContract ( ) ;
370
-
399
+
371
400
var codeHash = HashHelper . ComputeFrom ( input . Code . ToByteArray ( ) ) ;
372
401
Context . LogDebug ( ( ) => "BasicContractZero - Deployment user contract hash: " + codeHash . ToHex ( ) ) ;
373
-
374
- AssertContractExists ( codeHash ) ;
375
-
402
+
403
+ AssertContractNotExists ( codeHash ) ;
404
+
405
+ if ( input . Salt != null )
406
+ {
407
+ AssertContractAddressAvailable ( Context . Sender , input . Salt ) ;
408
+ }
409
+
376
410
var proposedContractInputHash = CalculateHashFromInput ( input ) ;
377
411
SendUserContractProposal ( proposedContractInputHash ,
378
412
nameof ( BasicContractZeroImplContainer . BasicContractZeroImplBase . PerformDeployUserSmartContract ) ,
@@ -394,23 +428,24 @@ public override DeployUserSmartContractOutput DeployUserSmartContract(ContractDe
394
428
} ;
395
429
}
396
430
397
- public override Empty UpdateUserSmartContract ( ContractUpdateInput input )
431
+ public override Empty UpdateUserSmartContract ( UserContractUpdateInput input )
398
432
{
399
433
AssertInlineDeployOrUpdateUserContract ( ) ;
400
-
434
+
401
435
var info = State . ContractInfos [ input . Address ] ;
402
436
Assert ( info != null , "Contract not found." ) ;
403
437
Assert ( Context . Sender == info . Author , "No permission." ) ;
438
+ Assert ( info . Deployer == null || info . Deployer == Context . Sender , "No permission to update." ) ;
404
439
var codeHash = HashHelper . ComputeFrom ( input . Code . ToByteArray ( ) ) ;
405
440
Assert ( info . CodeHash != codeHash , "Code is not changed." ) ;
406
- AssertContractExists ( codeHash ) ;
441
+ AssertContractNotExists ( codeHash ) ;
407
442
AssertContractVersion ( info . ContractVersion , input . Code , info . Category ) ;
408
-
443
+
409
444
var proposedContractInputHash = CalculateHashFromInput ( input ) ;
410
445
SendUserContractProposal ( proposedContractInputHash ,
411
446
nameof ( BasicContractZeroImplContainer . BasicContractZeroImplBase . PerformUpdateUserSmartContract ) ,
412
447
input . ToByteString ( ) ) ;
413
-
448
+
414
449
// Fire event to trigger BPs checking contract code
415
450
Context . Fire ( new CodeCheckRequired
416
451
{
@@ -420,10 +455,10 @@ public override Empty UpdateUserSmartContract(ContractUpdateInput input)
420
455
IsSystemContract = false ,
421
456
IsUserContract = true
422
457
} ) ;
423
-
458
+
424
459
return new Empty ( ) ;
425
460
}
426
-
461
+
427
462
public override Empty ReleaseApprovedUserSmartContract ( ReleaseContractInput input )
428
463
{
429
464
var contractProposingInput = State . ContractProposingInputMap [ input . ProposedContractInputHash ] ;
@@ -432,9 +467,9 @@ public override Empty ReleaseApprovedUserSmartContract(ReleaseContractInput inpu
432
467
contractProposingInput != null &&
433
468
contractProposingInput . Status == ContractProposingInputStatus . CodeCheckProposed &&
434
469
contractProposingInput . Proposer == Context . Self , "Invalid contract proposing status." ) ;
435
-
470
+
436
471
AssertCurrentMiner ( ) ;
437
-
472
+
438
473
contractProposingInput . Status = ContractProposingInputStatus . CodeChecked ;
439
474
State . ContractProposingInputMap [ input . ProposedContractInputHash ] = contractProposingInput ;
440
475
var codeCheckController = State . CodeCheckController . Value ;
@@ -443,27 +478,27 @@ public override Empty ReleaseApprovedUserSmartContract(ReleaseContractInput inpu
443
478
return new Empty ( ) ;
444
479
}
445
480
446
- public override Address PerformDeployUserSmartContract ( ContractDeploymentInput input )
481
+ public override Address PerformDeployUserSmartContract ( UserContractDeploymentInput input )
447
482
{
448
483
RequireSenderAuthority ( State . CodeCheckController . Value . OwnerAddress ) ;
449
484
450
485
var inputHash = CalculateHashFromInput ( input ) ;
451
486
TryClearContractProposingData ( inputHash , out var contractProposingInput ) ;
452
487
453
488
var address = DeploySmartContract ( null , input . Category , input . Code . ToByteArray ( ) , false ,
454
- contractProposingInput . Author , true ) ;
489
+ contractProposingInput . Author , true , contractProposingInput . Author , input . Salt ) ;
455
490
return address ;
456
491
}
457
492
458
- public override Empty PerformUpdateUserSmartContract ( ContractUpdateInput input )
493
+ public override Empty PerformUpdateUserSmartContract ( UserContractUpdateInput input )
459
494
{
460
495
RequireSenderAuthority ( State . CodeCheckController . Value . OwnerAddress ) ;
461
-
496
+
462
497
var inputHash = CalculateHashFromInput ( input ) ;
463
498
TryClearContractProposingData ( inputHash , out var proposingInput ) ;
464
499
465
500
UpdateSmartContract ( input . Address , input . Code . ToByteArray ( ) , proposingInput . Author , true ) ;
466
-
501
+
467
502
return new Empty ( ) ;
468
503
}
469
504
@@ -481,7 +516,23 @@ public override Empty SetContractAuthor(SetContractAuthorInput input)
481
516
OldAuthor = oldAuthor ,
482
517
NewAuthor = input . NewAuthor
483
518
} ) ;
484
-
519
+
520
+ return new Empty ( ) ;
521
+ }
522
+
523
+ public override Empty SetSigner ( Address input )
524
+ {
525
+ Assert ( input != null && ! input . Value . IsNullOrEmpty ( ) , "Invalid input." ) ;
526
+
527
+ if ( State . SignerMap [ Context . Sender ] == input ) return new Empty ( ) ;
528
+
529
+ State . SignerMap [ Context . Sender ] = input ;
530
+ return new Empty ( ) ;
531
+ }
532
+
533
+ public override Empty RemoveSigner ( Empty input )
534
+ {
535
+ RemoveOneTimeSigner ( Context . Sender ) ;
485
536
return new Empty ( ) ;
486
537
}
487
538
0 commit comments